HDDS-45. Removal of old OzoneRestClient. Contributed by Lokesh Jain.
This commit is contained in:
parent
c05b5d424b
commit
774daa8d53
@ -54,6 +54,7 @@ public class XceiverClient extends XceiverClientSpi {
|
||||
private Bootstrap b;
|
||||
private EventLoopGroup group;
|
||||
private final Semaphore semaphore;
|
||||
private boolean closed = false;
|
||||
|
||||
/**
|
||||
* Constructs a client that can communicate with the Container framework on
|
||||
@ -74,6 +75,10 @@ public XceiverClient(Pipeline pipeline, Configuration config) {
|
||||
|
||||
@Override
|
||||
public void connect() throws Exception {
|
||||
if (closed) {
|
||||
throw new IOException("This channel is not connected.");
|
||||
}
|
||||
|
||||
if (channel != null && channel.isActive()) {
|
||||
throw new IOException("This client is already connected to a host.");
|
||||
}
|
||||
@ -97,6 +102,18 @@ public void connect() throws Exception {
|
||||
channel = b.connect(leader.getHostName(), port).sync().channel();
|
||||
}
|
||||
|
||||
public void reconnect() throws IOException {
|
||||
try {
|
||||
connect();
|
||||
if (channel == null || !channel.isActive()) {
|
||||
throw new IOException("This channel is not connected.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error while connecting: ", e);
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the exceiver client connects to a server.
|
||||
*
|
||||
@ -109,6 +126,7 @@ public boolean isConnected() {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
closed = true;
|
||||
if (group != null) {
|
||||
group.shutdownGracefully().awaitUninterruptibly();
|
||||
}
|
||||
@ -124,7 +142,7 @@ public ContainerProtos.ContainerCommandResponseProto sendCommand(
|
||||
ContainerProtos.ContainerCommandRequestProto request) throws IOException {
|
||||
try {
|
||||
if ((channel == null) || (!channel.isActive())) {
|
||||
throw new IOException("This channel is not connected.");
|
||||
reconnect();
|
||||
}
|
||||
XceiverClientHandler handler =
|
||||
channel.pipeline().get(XceiverClientHandler.class);
|
||||
@ -160,7 +178,7 @@ public ContainerProtos.ContainerCommandResponseProto sendCommand(
|
||||
sendCommandAsync(ContainerProtos.ContainerCommandRequestProto request)
|
||||
throws IOException, ExecutionException, InterruptedException {
|
||||
if ((channel == null) || (!channel.isActive())) {
|
||||
throw new IOException("This channel is not connected.");
|
||||
reconnect();
|
||||
}
|
||||
XceiverClientHandler handler =
|
||||
channel.pipeline().get(XceiverClientHandler.class);
|
||||
|
@ -1,646 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hadoop.ozone.web.client;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.hadoop.fs.StorageType;
|
||||
import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
|
||||
import org.apache.hadoop.io.IOUtils;
|
||||
|
||||
import org.apache.hadoop.ozone.OzoneConsts;
|
||||
import org.apache.hadoop.ozone.client.OzoneClientException;
|
||||
import org.apache.hadoop.ozone.client.rest.OzoneException;
|
||||
import org.apache.hadoop.ozone.client.rest.headers.Header;
|
||||
import org.apache.hadoop.ozone.OzoneAcl;
|
||||
import org.apache.hadoop.ozone.web.response.BucketInfo;
|
||||
import org.apache.hadoop.ozone.web.response.KeyInfo;
|
||||
import org.apache.hadoop.ozone.web.response.ListKeys;
|
||||
|
||||
import static org.apache.hadoop.hdds.server.ServerUtils.releaseConnection;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.FileEntity;
|
||||
import org.apache.http.entity.InputStreamEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.net.HttpURLConnection.HTTP_CREATED;
|
||||
import static java.net.HttpURLConnection.HTTP_OK;
|
||||
import static org.apache.hadoop.ozone.web.utils.OzoneUtils.ENCODING;
|
||||
import static org.apache.hadoop.ozone.web.utils.OzoneUtils.ENCODING_NAME;
|
||||
|
||||
/**
|
||||
* A Bucket class the represents an Ozone Bucket.
|
||||
*/
|
||||
public class OzoneBucket {
|
||||
static final Logger LOG = LoggerFactory.getLogger(OzoneBucket.class);
|
||||
|
||||
private BucketInfo bucketInfo;
|
||||
private OzoneVolume volume;
|
||||
|
||||
/**
|
||||
* Constructor for bucket.
|
||||
*
|
||||
* @param info - BucketInfo
|
||||
* @param volume - OzoneVolume Object that contains this bucket
|
||||
*/
|
||||
public OzoneBucket(BucketInfo info, OzoneVolume volume) {
|
||||
this.bucketInfo = info;
|
||||
this.volume = volume;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets bucket Info.
|
||||
*
|
||||
* @return BucketInfo
|
||||
*/
|
||||
public BucketInfo getBucketInfo() {
|
||||
return bucketInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Bucket Info.
|
||||
*
|
||||
* @param bucketInfo BucketInfo
|
||||
*/
|
||||
public void setBucketInfo(BucketInfo bucketInfo) {
|
||||
this.bucketInfo = bucketInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent volume class.
|
||||
*
|
||||
* @return - OzoneVolume
|
||||
*/
|
||||
OzoneVolume getVolume() {
|
||||
return volume;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bucket name.
|
||||
*
|
||||
* @return Bucket Name
|
||||
*/
|
||||
public String getBucketName() {
|
||||
return bucketInfo.getBucketName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Acls on the bucket.
|
||||
*
|
||||
* @return - Acls
|
||||
*/
|
||||
public List<OzoneAcl> getAcls() {
|
||||
return bucketInfo.getAcls();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return versioning info on the bucket - Enabled or disabled.
|
||||
*
|
||||
* @return - Version Enum
|
||||
*/
|
||||
public OzoneConsts.Versioning getVersioning() {
|
||||
return bucketInfo.getVersioning();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Storage class for the bucket.
|
||||
*
|
||||
* @return Storage Class Enum
|
||||
*/
|
||||
public StorageType getStorageType() {
|
||||
return bucketInfo.getStorageType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the creation time of the bucket.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getCreatedOn() {
|
||||
return bucketInfo.getCreatedOn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an Object in Ozone bucket.
|
||||
*
|
||||
* @param keyName - Name of the key
|
||||
* @param data - Data that you want to put
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public void putKey(String keyName, String data) throws OzoneException {
|
||||
if ((keyName == null) || keyName.isEmpty()) {
|
||||
throw new OzoneClientException("Invalid key Name.");
|
||||
}
|
||||
|
||||
if (data == null) {
|
||||
throw new OzoneClientException("Invalid data.");
|
||||
}
|
||||
|
||||
HttpPut putRequest = null;
|
||||
InputStream is = null;
|
||||
try (CloseableHttpClient httpClient = HddsClientUtils.newHttpClient()) {
|
||||
URIBuilder builder = new URIBuilder(volume.getClient().getEndPointURI());
|
||||
builder.setPath("/" + getVolume().getVolumeName() + "/" + getBucketName()
|
||||
+ "/" + keyName).build();
|
||||
|
||||
putRequest = getVolume().getClient().getHttpPut(builder.toString());
|
||||
|
||||
is = new ByteArrayInputStream(data.getBytes(ENCODING));
|
||||
putRequest.setEntity(new InputStreamEntity(is, data.length()));
|
||||
is.mark(data.length());
|
||||
try {
|
||||
putRequest.setHeader(Header.CONTENT_MD5, DigestUtils.md5Hex(is));
|
||||
} finally {
|
||||
is.reset();
|
||||
}
|
||||
executePutKey(putRequest, httpClient);
|
||||
} catch (IOException | URISyntaxException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
IOUtils.closeStream(is);
|
||||
releaseConnection(putRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an Object in Ozone Bucket.
|
||||
*
|
||||
* @param dataFile - File from which you want the data to be put. Key Name
|
||||
* will same as the file name, devoid of any path.
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public void putKey(File dataFile) throws OzoneException {
|
||||
if (dataFile == null) {
|
||||
throw new OzoneClientException("Invalid file object.");
|
||||
}
|
||||
String keyName = dataFile.getName();
|
||||
putKey(keyName, dataFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a Key in Ozone Bucket.
|
||||
*
|
||||
* @param keyName - Name of the Key
|
||||
* @param file - Stream that gets read to be put into Ozone.
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public void putKey(String keyName, File file)
|
||||
throws OzoneException {
|
||||
|
||||
if ((keyName == null) || keyName.isEmpty()) {
|
||||
throw new OzoneClientException("Invalid key Name");
|
||||
}
|
||||
|
||||
if (file == null) {
|
||||
throw new OzoneClientException("Invalid data stream");
|
||||
}
|
||||
|
||||
HttpPut putRequest = null;
|
||||
FileInputStream fis = null;
|
||||
try (CloseableHttpClient httpClient = HddsClientUtils.newHttpClient()) {
|
||||
URIBuilder builder = new URIBuilder(volume.getClient().getEndPointURI());
|
||||
builder.setPath("/" + getVolume().getVolumeName() + "/" + getBucketName()
|
||||
+ "/" + keyName).build();
|
||||
|
||||
putRequest = getVolume().getClient().getHttpPut(builder.toString());
|
||||
|
||||
FileEntity fileEntity = new FileEntity(file, ContentType
|
||||
.APPLICATION_OCTET_STREAM);
|
||||
putRequest.setEntity(fileEntity);
|
||||
|
||||
fis = new FileInputStream(file);
|
||||
putRequest.setHeader(Header.CONTENT_MD5, DigestUtils.md5Hex(fis));
|
||||
executePutKey(putRequest, httpClient);
|
||||
|
||||
} catch (IOException | URISyntaxException ex) {
|
||||
final OzoneClientException orce = new OzoneClientException(
|
||||
"Failed to putKey: keyName=" + keyName + ", file=" + file);
|
||||
orce.initCause(ex);
|
||||
LOG.trace("", orce);
|
||||
throw orce;
|
||||
} finally {
|
||||
IOUtils.closeStream(fis);
|
||||
releaseConnection(putRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* executePutKey executes the Put request against the Ozone Server.
|
||||
*
|
||||
* @param putRequest - Http Put Request
|
||||
* @param httpClient - httpClient
|
||||
* @throws OzoneException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void executePutKey(HttpPut putRequest,
|
||||
CloseableHttpClient httpClient) throws OzoneException, IOException {
|
||||
HttpEntity entity = null;
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(putRequest);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
entity = response.getEntity();
|
||||
|
||||
if ((errorCode == HTTP_OK) || (errorCode == HTTP_CREATED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity == null) {
|
||||
throw new OzoneClientException("Unexpected null in http payload");
|
||||
}
|
||||
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a key from the Ozone server and writes to the file pointed by the
|
||||
* downloadTo PAth.
|
||||
*
|
||||
* @param keyName - Key Name in Ozone.
|
||||
* @param downloadTo File Name to download the Key's Data to
|
||||
*/
|
||||
public void getKey(String keyName, Path downloadTo) throws OzoneException {
|
||||
|
||||
if ((keyName == null) || keyName.isEmpty()) {
|
||||
throw new OzoneClientException("Invalid key Name");
|
||||
}
|
||||
|
||||
if (downloadTo == null) {
|
||||
throw new OzoneClientException("Invalid download path");
|
||||
}
|
||||
|
||||
FileOutputStream outPutFile = null;
|
||||
HttpGet getRequest = null;
|
||||
try (CloseableHttpClient httpClient = HddsClientUtils.newHttpClient()) {
|
||||
outPutFile = new FileOutputStream(downloadTo.toFile());
|
||||
|
||||
URIBuilder builder = new URIBuilder(volume.getClient().getEndPointURI());
|
||||
builder.setPath("/" + getVolume().getVolumeName() + "/" + getBucketName()
|
||||
+ "/" + keyName).build();
|
||||
|
||||
getRequest = getVolume().getClient().getHttpGet(builder.toString());
|
||||
executeGetKey(getRequest, httpClient, outPutFile);
|
||||
outPutFile.flush();
|
||||
} catch (IOException | URISyntaxException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
IOUtils.closeStream(outPutFile);
|
||||
releaseConnection(getRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data part of the key as a string.
|
||||
*
|
||||
* @param keyName - KeyName to get
|
||||
* @return String - Data
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public String getKey(String keyName) throws OzoneException {
|
||||
|
||||
if ((keyName == null) || keyName.isEmpty()) {
|
||||
throw new OzoneClientException("Invalid key Name");
|
||||
}
|
||||
|
||||
HttpGet getRequest = null;
|
||||
ByteArrayOutputStream outPutStream = null;
|
||||
try (CloseableHttpClient httpClient = HddsClientUtils.newHttpClient()) {
|
||||
outPutStream = new ByteArrayOutputStream();
|
||||
|
||||
URIBuilder builder = new URIBuilder(volume.getClient().getEndPointURI());
|
||||
|
||||
builder.setPath("/" + getVolume().getVolumeName() + "/" + getBucketName()
|
||||
+ "/" + keyName).build();
|
||||
|
||||
getRequest = getVolume().getClient().getHttpGet(builder.toString());
|
||||
executeGetKey(getRequest, httpClient, outPutStream);
|
||||
return outPutStream.toString(ENCODING_NAME);
|
||||
} catch (IOException | URISyntaxException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
IOUtils.closeStream(outPutStream);
|
||||
releaseConnection(getRequest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes get key and returns the data.
|
||||
*
|
||||
* @param getRequest - http Get Request
|
||||
* @param httpClient - Client
|
||||
* @param stream - Stream to write data to.
|
||||
* @throws IOException
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public static void executeGetKey(HttpGet getRequest,
|
||||
CloseableHttpClient httpClient, OutputStream stream)
|
||||
throws IOException, OzoneException {
|
||||
|
||||
HttpEntity entity = null;
|
||||
try {
|
||||
|
||||
HttpResponse response = httpClient.execute(getRequest);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
entity = response.getEntity();
|
||||
|
||||
if (errorCode == HTTP_OK) {
|
||||
entity.writeTo(stream);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity == null) {
|
||||
throw new OzoneClientException("Unexpected null in http payload");
|
||||
}
|
||||
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a key in this bucket.
|
||||
*
|
||||
* @param keyName - Name of the Key
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public void deleteKey(String keyName) throws OzoneException {
|
||||
|
||||
if ((keyName == null) || keyName.isEmpty()) {
|
||||
throw new OzoneClientException("Invalid key Name");
|
||||
}
|
||||
|
||||
HttpDelete deleteRequest = null;
|
||||
try (CloseableHttpClient httpClient = HddsClientUtils.newHttpClient()) {
|
||||
URIBuilder builder = new URIBuilder(volume.getClient().getEndPointURI());
|
||||
builder.setPath("/" + getVolume().getVolumeName() + "/" + getBucketName()
|
||||
+ "/" + keyName).build();
|
||||
|
||||
deleteRequest = getVolume()
|
||||
.getClient().getHttpDelete(builder.toString());
|
||||
executeDeleteKey(deleteRequest, httpClient);
|
||||
} catch (IOException | URISyntaxException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
releaseConnection(deleteRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes deleteKey.
|
||||
*
|
||||
* @param deleteRequest - http Delete Request
|
||||
* @param httpClient - Client
|
||||
* @throws IOException
|
||||
* @throws OzoneException
|
||||
*/
|
||||
private void executeDeleteKey(HttpDelete deleteRequest,
|
||||
CloseableHttpClient httpClient)
|
||||
throws IOException, OzoneException {
|
||||
|
||||
HttpEntity entity = null;
|
||||
try {
|
||||
|
||||
HttpResponse response = httpClient.execute(deleteRequest);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
entity = response.getEntity();
|
||||
|
||||
if (errorCode == HTTP_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity == null) {
|
||||
throw new OzoneClientException("Unexpected null in http payload");
|
||||
}
|
||||
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all keys in a bucket.
|
||||
*
|
||||
* @param resultLength The max length of listing result.
|
||||
* @param previousKey The key from where listing should start,
|
||||
* this key is excluded in the result.
|
||||
* @param prefix The prefix that return list keys start with.
|
||||
* @return List of OzoneKeys
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public List<OzoneKey> listKeys(String resultLength, String previousKey,
|
||||
String prefix) throws OzoneException {
|
||||
HttpGet getRequest = null;
|
||||
try (CloseableHttpClient httpClient = HddsClientUtils.newHttpClient()) {
|
||||
OzoneRestClient client = getVolume().getClient();
|
||||
URIBuilder builder = new URIBuilder(volume.getClient().getEndPointURI());
|
||||
builder.setPath("/" + getVolume().getVolumeName() + "/" + getBucketName())
|
||||
.build();
|
||||
|
||||
if (!Strings.isNullOrEmpty(resultLength)) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_MAXKEYS, resultLength);
|
||||
}
|
||||
|
||||
if (!Strings.isNullOrEmpty(previousKey)) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_PREVKEY, previousKey);
|
||||
}
|
||||
|
||||
if (!Strings.isNullOrEmpty(prefix)) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_PREFIX, prefix);
|
||||
}
|
||||
|
||||
final String uri = builder.toString();
|
||||
getRequest = client.getHttpGet(uri);
|
||||
LOG.trace("listKeys URI={}", uri);
|
||||
return executeListKeys(getRequest, httpClient);
|
||||
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
throw new OzoneClientException(e.getMessage(), e);
|
||||
} finally {
|
||||
releaseConnection(getRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List keys in a bucket with the provided prefix, with paging results.
|
||||
*
|
||||
* @param prefix The prefix of the object keys
|
||||
* @param maxResult max size per response
|
||||
* @param prevKey the previous key for paging
|
||||
*/
|
||||
public List<OzoneKey> listKeys(String prefix, int maxResult, String prevKey)
|
||||
throws OzoneException {
|
||||
HttpGet getRequest = null;
|
||||
try {
|
||||
final URI uri = new URIBuilder(volume.getClient().getEndPointURI())
|
||||
.setPath(OzoneConsts.KSM_KEY_PREFIX + getVolume().getVolumeName() +
|
||||
OzoneConsts.KSM_KEY_PREFIX + getBucketName())
|
||||
.setParameter(Header.OZONE_LIST_QUERY_PREFIX, prefix)
|
||||
.setParameter(Header.OZONE_LIST_QUERY_MAXKEYS,
|
||||
String.valueOf(maxResult))
|
||||
.setParameter(Header.OZONE_LIST_QUERY_PREVKEY, prevKey)
|
||||
.build();
|
||||
final OzoneRestClient client = getVolume().getClient();
|
||||
getRequest = client.getHttpGet(uri.toString());
|
||||
return executeListKeys(getRequest, HttpClientBuilder.create().build());
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
throw new OzoneClientException(e.getMessage());
|
||||
} finally {
|
||||
releaseConnection(getRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute list Key.
|
||||
*
|
||||
* @param getRequest - HttpGet
|
||||
* @param httpClient - HttpClient
|
||||
* @return List<OzoneKey>
|
||||
* @throws IOException
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public static List<OzoneKey> executeListKeys(HttpGet getRequest,
|
||||
CloseableHttpClient httpClient) throws IOException, OzoneException {
|
||||
HttpEntity entity = null;
|
||||
List<OzoneKey> ozoneKeyList = new LinkedList<OzoneKey>();
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(getRequest);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
|
||||
entity = response.getEntity();
|
||||
|
||||
if (entity == null) {
|
||||
throw new OzoneClientException("Unexpected null in http payload");
|
||||
}
|
||||
if (errorCode == HTTP_OK) {
|
||||
String temp = EntityUtils.toString(entity);
|
||||
ListKeys keyList = ListKeys.parse(temp);
|
||||
|
||||
for (KeyInfo info : keyList.getKeyList()) {
|
||||
ozoneKeyList.add(new OzoneKey(info));
|
||||
}
|
||||
return ozoneKeyList;
|
||||
|
||||
} else {
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
}
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info of the specified key.
|
||||
*/
|
||||
public OzoneKey getKeyInfo(String keyName) throws OzoneException {
|
||||
if ((keyName == null) || keyName.isEmpty()) {
|
||||
throw new OzoneClientException(
|
||||
"Unable to get key info, key name is null or empty");
|
||||
}
|
||||
|
||||
HttpGet getRequest = null;
|
||||
try (CloseableHttpClient httpClient = HddsClientUtils.newHttpClient()) {
|
||||
OzoneRestClient client = getVolume().getClient();
|
||||
URIBuilder builder = new URIBuilder(volume.getClient().getEndPointURI());
|
||||
builder
|
||||
.setPath("/" + getVolume().getVolumeName() + "/" + getBucketName()
|
||||
+ "/" + keyName)
|
||||
.setParameter(Header.OZONE_INFO_QUERY_TAG,
|
||||
Header.OZONE_INFO_QUERY_KEY)
|
||||
.build();
|
||||
|
||||
getRequest = client.getHttpGet(builder.toString());
|
||||
return executeGetKeyInfo(getRequest, httpClient);
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
throw new OzoneClientException(e.getMessage(), e);
|
||||
} finally {
|
||||
releaseConnection(getRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute get Key info.
|
||||
*
|
||||
* @param getRequest - HttpGet
|
||||
* @param httpClient - HttpClient
|
||||
* @return List<OzoneKey>
|
||||
* @throws IOException
|
||||
* @throws OzoneException
|
||||
*/
|
||||
private OzoneKey executeGetKeyInfo(HttpGet getRequest,
|
||||
CloseableHttpClient httpClient) throws IOException, OzoneException {
|
||||
HttpEntity entity = null;
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(getRequest);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
entity = response.getEntity();
|
||||
if (entity == null) {
|
||||
throw new OzoneClientException("Unexpected null in http payload");
|
||||
}
|
||||
|
||||
if (errorCode == HTTP_OK) {
|
||||
OzoneKey key = new OzoneKey(
|
||||
KeyInfo.parse(EntityUtils.toString(entity)));
|
||||
return key;
|
||||
}
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.hadoop.ozone.web.client;
|
||||
|
||||
import org.apache.hadoop.ozone.web.response.KeyInfo;
|
||||
|
||||
/**
|
||||
* Client side representation of an ozone Key.
|
||||
*/
|
||||
public class OzoneKey {
|
||||
private KeyInfo keyInfo;
|
||||
|
||||
/**
|
||||
* Constructor for Ozone Key.
|
||||
* @param keyInfo - Key Info
|
||||
*/
|
||||
public OzoneKey(KeyInfo keyInfo) {
|
||||
this.keyInfo = keyInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Key Info.
|
||||
* @return Object Info
|
||||
*/
|
||||
public KeyInfo getObjectInfo() {
|
||||
return keyInfo;
|
||||
}
|
||||
|
||||
}
|
@ -1,804 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.hadoop.ozone.web.client;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
|
||||
import org.apache.hadoop.io.IOUtils;
|
||||
import org.apache.hadoop.ozone.client.OzoneClientException;
|
||||
import org.apache.hadoop.ozone.client.rest.OzoneException;
|
||||
import org.apache.hadoop.ozone.client.rest.headers.Header;
|
||||
import org.apache.hadoop.ozone.web.response.ListVolumes;
|
||||
import org.apache.hadoop.ozone.web.response.VolumeInfo;
|
||||
import org.apache.hadoop.ozone.web.utils.OzoneUtils;
|
||||
import org.apache.hadoop.util.Time;
|
||||
|
||||
import static org.apache.hadoop.hdds.server.ServerUtils.releaseConnection;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.FileEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static java.net.HttpURLConnection.HTTP_CREATED;
|
||||
import static java.net.HttpURLConnection.HTTP_OK;
|
||||
|
||||
/**
|
||||
* Ozone client that connects to an Ozone server. Please note that this class is
|
||||
* not thread safe.
|
||||
*/
|
||||
public class OzoneRestClient implements Closeable {
|
||||
private URI endPointURI;
|
||||
private String userAuth;
|
||||
|
||||
/**
|
||||
* Constructor for OzoneRestClient.
|
||||
*/
|
||||
public OzoneRestClient() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for OzoneRestClient.
|
||||
*/
|
||||
public OzoneRestClient(String ozoneURI)
|
||||
throws OzoneException, URISyntaxException {
|
||||
setEndPoint(ozoneURI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for OzoneRestClient.
|
||||
*/
|
||||
public OzoneRestClient(String ozoneURI, String userAuth)
|
||||
throws OzoneException, URISyntaxException {
|
||||
setEndPoint(ozoneURI);
|
||||
setUserAuth(userAuth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the end Point.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public URI getEndPointURI() {
|
||||
return endPointURI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the End Point info using an URI.
|
||||
*
|
||||
* @param endPointURI - URI
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public void setEndPointURI(URI endPointURI) throws OzoneException {
|
||||
if ((endPointURI == null) || (endPointURI.toString().isEmpty())) {
|
||||
throw new OzoneClientException("Invalid ozone URI");
|
||||
}
|
||||
this.endPointURI = endPointURI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set endPoint.
|
||||
*
|
||||
* @param clusterFQDN - cluster FQDN.
|
||||
*/
|
||||
public void setEndPoint(String clusterFQDN) throws
|
||||
OzoneException, URISyntaxException {
|
||||
setEndPointURI(new URI(clusterFQDN));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user Auth String.
|
||||
*
|
||||
* @return - User Auth String
|
||||
*/
|
||||
public String getUserAuth() {
|
||||
return this.userAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set User Auth.
|
||||
*
|
||||
* @param userAuth - User Auth String
|
||||
*/
|
||||
public void setUserAuth(String userAuth) {
|
||||
this.userAuth = userAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* create volume.
|
||||
*
|
||||
* @param volumeName - volume name 3 - 63 chars, small letters.
|
||||
* @param onBehalfOf - The user on behalf we are making the call for
|
||||
* @param quota - Quota's are specified in a specific format. it is
|
||||
* integer(MB|GB|TB), for example 100TB.
|
||||
* @throws OzoneClientException
|
||||
*/
|
||||
public OzoneVolume createVolume(String volumeName, String onBehalfOf,
|
||||
String quota) throws OzoneException {
|
||||
HttpPost httpPost = null;
|
||||
try (CloseableHttpClient httpClient = newHttpClient()) {
|
||||
OzoneUtils.verifyResourceName(volumeName);
|
||||
|
||||
URIBuilder builder = new URIBuilder(endPointURI);
|
||||
builder.setPath("/" + volumeName);
|
||||
if (quota != null) {
|
||||
builder.setParameter(Header.OZONE_QUOTA_QUERY_TAG, quota);
|
||||
}
|
||||
|
||||
httpPost = getHttpPost(onBehalfOf, builder.build().toString());
|
||||
executeCreateVolume(httpPost, httpClient);
|
||||
return getVolume(volumeName);
|
||||
} catch (IOException | URISyntaxException | IllegalArgumentException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
releaseConnection(httpPost);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about an existing Volume. if the Volume does not exist,
|
||||
* or if the user does not have access rights OzoneException is thrown
|
||||
*
|
||||
* @param volumeName - volume name 3 - 63 chars, small letters.
|
||||
* @return OzoneVolume Ozone Client Volume Class.
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public OzoneVolume getVolume(String volumeName) throws OzoneException {
|
||||
HttpGet httpGet = null;
|
||||
try (CloseableHttpClient httpClient = newHttpClient()) {
|
||||
OzoneUtils.verifyResourceName(volumeName);
|
||||
URIBuilder builder = new URIBuilder(endPointURI);
|
||||
builder.setPath("/" + volumeName)
|
||||
.setParameter(Header.OZONE_INFO_QUERY_TAG,
|
||||
Header.OZONE_INFO_QUERY_VOLUME)
|
||||
.build();
|
||||
|
||||
httpGet = getHttpGet(builder.toString());
|
||||
return executeInfoVolume(httpGet, httpClient);
|
||||
} catch (IOException | URISyntaxException | IllegalArgumentException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
releaseConnection(httpGet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all the volumes owned by the user or Owned by the user specified in
|
||||
* the behalf of string.
|
||||
*
|
||||
* @param onBehalfOf
|
||||
* User Name of the user if it is not the caller. for example,
|
||||
* an admin wants to list some other users volumes.
|
||||
* @param prefix
|
||||
* Return only volumes that match this prefix.
|
||||
* @param maxKeys
|
||||
* Maximum number of results to return, if the result set
|
||||
* is smaller than requested size, it means that list is
|
||||
* complete.
|
||||
* @param previousVolume
|
||||
* The previous volume name.
|
||||
* @return List of Volumes
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public List<OzoneVolume> listVolumes(String onBehalfOf, String prefix,
|
||||
int maxKeys, String previousVolume) throws OzoneException {
|
||||
HttpGet httpGet = null;
|
||||
try (CloseableHttpClient httpClient = newHttpClient()) {
|
||||
URIBuilder builder = new URIBuilder(endPointURI);
|
||||
if (!Strings.isNullOrEmpty(prefix)) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_PREFIX, prefix);
|
||||
}
|
||||
|
||||
if (maxKeys > 0) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_MAXKEYS, Integer
|
||||
.toString(maxKeys));
|
||||
}
|
||||
|
||||
if (!Strings.isNullOrEmpty(previousVolume)) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_PREVKEY,
|
||||
previousVolume);
|
||||
}
|
||||
|
||||
builder.setPath("/").build();
|
||||
|
||||
httpGet = getHttpGet(builder.toString());
|
||||
if (onBehalfOf != null) {
|
||||
httpGet.addHeader(Header.OZONE_USER, onBehalfOf);
|
||||
}
|
||||
return executeListVolume(httpGet, httpClient);
|
||||
} catch (IOException | URISyntaxException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
releaseConnection(httpGet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all the volumes owned by the user or Owned by the user specified in
|
||||
* the behalf of string.
|
||||
*
|
||||
* @param onBehalfOf - User Name of the user if it is not the caller. for
|
||||
* example, an admin wants to list some other users
|
||||
* volumes.
|
||||
* @param prefix - Return only volumes that match this prefix.
|
||||
* @param maxKeys - Maximum number of results to return, if the result set
|
||||
* is smaller than requested size, it means that list is
|
||||
* complete.
|
||||
* @param prevKey - The last key that client got, server will continue
|
||||
* returning results from that point.
|
||||
* @return List of Volumes
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public List<OzoneVolume> listVolumes(String onBehalfOf, String prefix,
|
||||
int maxKeys, OzoneVolume prevKey) throws OzoneException {
|
||||
String volumeName = null;
|
||||
|
||||
if (prevKey != null) {
|
||||
volumeName = prevKey.getVolumeName();
|
||||
}
|
||||
|
||||
return listVolumes(onBehalfOf, prefix, maxKeys, volumeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* List volumes of the current user or if onBehalfof is not null lists volume
|
||||
* owned by that user. You need admin privilege to read other users volume
|
||||
* lists.
|
||||
*
|
||||
* @param onBehalfOf - Name of the user you want to get volume list
|
||||
* @return - Volume list.
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public List<OzoneVolume> listVolumes(String onBehalfOf)
|
||||
throws OzoneException {
|
||||
return listVolumes(onBehalfOf, null,
|
||||
Integer.parseInt(Header.OZONE_DEFAULT_LIST_SIZE), StringUtils.EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all volumes in a cluster. This can be invoked only by an Admin.
|
||||
*
|
||||
* @param prefix - Returns only volumes that match this prefix.
|
||||
* @param maxKeys - Maximum niumber of keys to return
|
||||
* @param prevKey - Last Ozone Volume from the last Iteration.
|
||||
* @return List of Volumes
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public List<OzoneVolume> listAllVolumes(String prefix, int maxKeys,
|
||||
OzoneVolume prevKey) throws OzoneException {
|
||||
HttpGet httpGet = null;
|
||||
try (CloseableHttpClient httpClient = newHttpClient()) {
|
||||
URIBuilder builder = new URIBuilder(endPointURI);
|
||||
if (prefix != null) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_PREFIX, prefix);
|
||||
}
|
||||
|
||||
if (maxKeys > 0) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_MAXKEYS, Integer
|
||||
.toString(maxKeys));
|
||||
}
|
||||
|
||||
if (prevKey != null) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_PREVKEY,
|
||||
prevKey.getOwnerName()+ "/" + prevKey.getVolumeName());
|
||||
}
|
||||
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_ROOTSCAN, "true");
|
||||
builder.setPath("/").build();
|
||||
httpGet = getHttpGet(builder.toString());
|
||||
return executeListVolume(httpGet, httpClient);
|
||||
|
||||
} catch (IOException | URISyntaxException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
releaseConnection(httpGet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* delete a given volume.
|
||||
*
|
||||
* @param volumeName - volume to be deleted.
|
||||
* @throws OzoneException - Ozone Exception
|
||||
*/
|
||||
public void deleteVolume(String volumeName) throws OzoneException {
|
||||
HttpDelete httpDelete = null;
|
||||
try (CloseableHttpClient httpClient = newHttpClient()) {
|
||||
OzoneUtils.verifyResourceName(volumeName);
|
||||
URIBuilder builder = new URIBuilder(endPointURI);
|
||||
builder.setPath("/" + volumeName).build();
|
||||
|
||||
httpDelete = getHttpDelete(builder.toString());
|
||||
executeDeleteVolume(httpDelete, httpClient);
|
||||
} catch (IOException | URISyntaxException | IllegalArgumentException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
releaseConnection(httpDelete);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Volume Owner.
|
||||
*
|
||||
* @param volumeName - Volume Name
|
||||
* @param newOwner - New Owner Name
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public void setVolumeOwner(String volumeName, String newOwner)
|
||||
throws OzoneException {
|
||||
HttpPut putRequest = null;
|
||||
if (newOwner == null || newOwner.isEmpty()) {
|
||||
throw new OzoneClientException("Invalid new owner name");
|
||||
}
|
||||
try (CloseableHttpClient httpClient = newHttpClient()) {
|
||||
OzoneUtils.verifyResourceName(volumeName);
|
||||
URIBuilder builder = new URIBuilder(endPointURI);
|
||||
builder.setPath("/" + volumeName).build();
|
||||
|
||||
putRequest = getHttpPut(builder.toString());
|
||||
putRequest.addHeader(Header.OZONE_USER, newOwner);
|
||||
executePutVolume(putRequest, httpClient);
|
||||
|
||||
} catch (URISyntaxException | IllegalArgumentException | IOException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
releaseConnection(putRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Volume Quota. Quota's are specified in a specific format. it is
|
||||
* <integer>|(MB|GB|TB. for example 100TB.
|
||||
* <p>
|
||||
* To Remove a quota you can specify Header.OZONE_QUOTA_REMOVE
|
||||
*
|
||||
* @param volumeName - volume name
|
||||
* @param quota - Quota String or Header.OZONE_QUOTA_REMOVE
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public void setVolumeQuota(String volumeName, String quota)
|
||||
throws OzoneException {
|
||||
if (quota == null || quota.isEmpty()) {
|
||||
throw new OzoneClientException("Invalid quota");
|
||||
}
|
||||
HttpPut putRequest = null;
|
||||
try (CloseableHttpClient httpClient = newHttpClient()) {
|
||||
OzoneUtils.verifyResourceName(volumeName);
|
||||
URIBuilder builder = new URIBuilder(endPointURI);
|
||||
builder.setPath("/" + volumeName)
|
||||
.setParameter(Header.OZONE_QUOTA_QUERY_TAG, quota)
|
||||
.build();
|
||||
|
||||
putRequest = getHttpPut(builder.toString());
|
||||
executePutVolume(putRequest, httpClient);
|
||||
|
||||
} catch (URISyntaxException | IllegalArgumentException | IOException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
releaseConnection(putRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the create Volume request to the server.
|
||||
*
|
||||
* @param httppost - http post class
|
||||
* @param httpClient - httpClient
|
||||
* @throws IOException -
|
||||
* @throws OzoneException
|
||||
*/
|
||||
private void executeCreateVolume(HttpPost httppost,
|
||||
final CloseableHttpClient httpClient)
|
||||
throws IOException, OzoneException {
|
||||
HttpEntity entity = null;
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(httppost);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
entity = response.getEntity();
|
||||
|
||||
if ((errorCode == HTTP_OK) || (errorCode == HTTP_CREATED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity != null) {
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
} else {
|
||||
throw new OzoneClientException("Unexpected null in http payload");
|
||||
}
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consume(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the create Volume request to the server.
|
||||
*
|
||||
* @param httpGet - httpGet
|
||||
* @return OzoneVolume
|
||||
* @throws IOException -
|
||||
* @throws OzoneException
|
||||
*/
|
||||
private OzoneVolume executeInfoVolume(HttpGet httpGet,
|
||||
final CloseableHttpClient httpClient)
|
||||
throws IOException, OzoneException {
|
||||
HttpEntity entity = null;
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(httpGet);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
|
||||
entity = response.getEntity();
|
||||
if (entity == null) {
|
||||
throw new OzoneClientException("Unexpected null in http payload");
|
||||
}
|
||||
|
||||
if (errorCode == HTTP_OK) {
|
||||
OzoneVolume volume = new OzoneVolume(this);
|
||||
volume.setVolumeInfo(EntityUtils.toString(entity));
|
||||
return volume;
|
||||
} else {
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
}
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends update volume requests to the server.
|
||||
*
|
||||
* @param putRequest http request
|
||||
* @throws IOException
|
||||
* @throws OzoneException
|
||||
*/
|
||||
private void executePutVolume(HttpPut putRequest,
|
||||
final CloseableHttpClient httpClient)
|
||||
throws IOException, OzoneException {
|
||||
HttpEntity entity = null;
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(putRequest);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
entity = response.getEntity();
|
||||
if (errorCode != HTTP_OK) {
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
}
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consume(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List Volumes.
|
||||
*
|
||||
* @param httpGet - httpGet
|
||||
* @return OzoneVolume
|
||||
* @throws IOException -
|
||||
* @throws OzoneException
|
||||
*/
|
||||
private List<OzoneVolume> executeListVolume(HttpGet httpGet,
|
||||
final CloseableHttpClient httpClient)
|
||||
throws IOException, OzoneException {
|
||||
HttpEntity entity = null;
|
||||
List<OzoneVolume> volList = new LinkedList<>();
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(httpGet);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
entity = response.getEntity();
|
||||
|
||||
if (entity == null) {
|
||||
throw new OzoneClientException("Unexpected null in http payload");
|
||||
}
|
||||
|
||||
String temp = EntityUtils.toString(entity);
|
||||
if (errorCode == HTTP_OK) {
|
||||
ListVolumes listVolumes =
|
||||
ListVolumes.parse(temp);
|
||||
|
||||
for (VolumeInfo info : listVolumes.getVolumes()) {
|
||||
volList.add(new OzoneVolume(info, this));
|
||||
}
|
||||
return volList;
|
||||
|
||||
} else {
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
}
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Volume.
|
||||
*
|
||||
* @param httpDelete - Http Delete Request
|
||||
* @throws IOException
|
||||
* @throws OzoneException
|
||||
*/
|
||||
private void executeDeleteVolume(HttpDelete httpDelete,
|
||||
final CloseableHttpClient httpClient)
|
||||
throws IOException, OzoneException {
|
||||
HttpEntity entity = null;
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(httpDelete);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
entity = response.getEntity();
|
||||
|
||||
if (errorCode != HTTP_OK) {
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
}
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a Key in Ozone Bucket.
|
||||
*
|
||||
* @param volumeName - Name of the Volume
|
||||
* @param bucketName - Name of the Bucket
|
||||
* @param keyName - Name of the Key
|
||||
* @param file - Stream that gets read to be put into Ozone.
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public void putKey(String volumeName, String bucketName, String keyName,
|
||||
File file) throws OzoneException {
|
||||
OzoneUtils.verifyResourceName(volumeName);
|
||||
OzoneUtils.verifyResourceName(bucketName);
|
||||
|
||||
if (StringUtils.isEmpty(keyName)) {
|
||||
throw new OzoneClientException("Invalid key Name");
|
||||
}
|
||||
|
||||
if (file == null) {
|
||||
throw new OzoneClientException("Invalid data stream");
|
||||
}
|
||||
|
||||
HttpPut putRequest = null;
|
||||
FileInputStream fis = null;
|
||||
try (CloseableHttpClient httpClient = HddsClientUtils.newHttpClient()) {
|
||||
URIBuilder builder = new URIBuilder(getEndPointURI());
|
||||
builder.setPath("/" + volumeName + "/" + bucketName + "/" + keyName)
|
||||
.build();
|
||||
|
||||
putRequest = getHttpPut(builder.toString());
|
||||
|
||||
FileEntity fileEntity = new FileEntity(file, ContentType
|
||||
.APPLICATION_OCTET_STREAM);
|
||||
putRequest.setEntity(fileEntity);
|
||||
|
||||
fis = new FileInputStream(file);
|
||||
putRequest.setHeader(Header.CONTENT_MD5, DigestUtils.md5Hex(fis));
|
||||
OzoneBucket.executePutKey(putRequest, httpClient);
|
||||
} catch (IOException | URISyntaxException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
IOUtils.closeStream(fis);
|
||||
releaseConnection(putRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a key from the Ozone server and writes to the file pointed by the
|
||||
* downloadTo Path.
|
||||
*
|
||||
* @param volumeName - Volume Name in Ozone.
|
||||
* @param bucketName - Bucket Name in Ozone.
|
||||
* @param keyName - Key Name in Ozone.
|
||||
* @param downloadTo File Name to download the Key's Data to
|
||||
*/
|
||||
public void getKey(String volumeName, String bucketName, String keyName,
|
||||
Path downloadTo) throws OzoneException {
|
||||
OzoneUtils.verifyResourceName(volumeName);
|
||||
OzoneUtils.verifyResourceName(bucketName);
|
||||
|
||||
if (StringUtils.isEmpty(keyName)) {
|
||||
throw new OzoneClientException("Invalid key Name");
|
||||
}
|
||||
|
||||
if (downloadTo == null) {
|
||||
throw new OzoneClientException("Invalid download path");
|
||||
}
|
||||
|
||||
FileOutputStream outPutFile = null;
|
||||
HttpGet getRequest = null;
|
||||
try (CloseableHttpClient httpClient = HddsClientUtils.newHttpClient()) {
|
||||
outPutFile = new FileOutputStream(downloadTo.toFile());
|
||||
|
||||
URIBuilder builder = new URIBuilder(getEndPointURI());
|
||||
builder.setPath("/" + volumeName + "/" + bucketName + "/" + keyName)
|
||||
.build();
|
||||
|
||||
getRequest = getHttpGet(builder.toString());
|
||||
OzoneBucket.executeGetKey(getRequest, httpClient, outPutFile);
|
||||
outPutFile.flush();
|
||||
} catch (IOException | URISyntaxException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
IOUtils.closeStream(outPutFile);
|
||||
releaseConnection(getRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all keys in the given bucket.
|
||||
*
|
||||
* @param volumeName - Volume name
|
||||
* @param bucketName - Bucket name
|
||||
* @param resultLength The max length of listing result.
|
||||
* @param previousKey The key from where listing should start,
|
||||
* this key is excluded in the result.
|
||||
* @param prefix The prefix that return list keys start with.
|
||||
*
|
||||
* @return List of OzoneKeys
|
||||
*/
|
||||
public List<OzoneKey> listKeys(String volumeName, String bucketName,
|
||||
String resultLength, String previousKey, String prefix)
|
||||
throws OzoneException {
|
||||
OzoneUtils.verifyResourceName(volumeName);
|
||||
OzoneUtils.verifyResourceName(bucketName);
|
||||
|
||||
HttpGet getRequest = null;
|
||||
try (CloseableHttpClient httpClient = HddsClientUtils.newHttpClient()) {
|
||||
URIBuilder builder = new URIBuilder(getEndPointURI());
|
||||
builder.setPath("/" + volumeName + "/" + bucketName).build();
|
||||
|
||||
if (!Strings.isNullOrEmpty(resultLength)) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_MAXKEYS, resultLength);
|
||||
}
|
||||
|
||||
if (!Strings.isNullOrEmpty(previousKey)) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_PREVKEY, previousKey);
|
||||
}
|
||||
|
||||
if (!Strings.isNullOrEmpty(prefix)) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_PREFIX, prefix);
|
||||
}
|
||||
|
||||
getRequest = getHttpGet(builder.toString());
|
||||
return OzoneBucket.executeListKeys(getRequest, httpClient);
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
throw new OzoneClientException(e.getMessage(), e);
|
||||
} finally {
|
||||
releaseConnection(getRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a standard HttpPost Object to use for ozone post requests.
|
||||
*
|
||||
* @param onBehalfOf - If the use is being made on behalf of user, that user
|
||||
* @param uriString - UriString
|
||||
* @return HttpPost
|
||||
*/
|
||||
public HttpPost getHttpPost(String onBehalfOf, String uriString) {
|
||||
HttpPost httpPost = new HttpPost(uriString);
|
||||
addOzoneHeaders(httpPost);
|
||||
if (onBehalfOf != null) {
|
||||
httpPost.addHeader(Header.OZONE_USER, onBehalfOf);
|
||||
}
|
||||
return httpPost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a standard HttpGet Object to use for ozone Get requests.
|
||||
*
|
||||
* @param uriString - The full Uri String
|
||||
* @return HttpGet
|
||||
*/
|
||||
public HttpGet getHttpGet(String uriString) {
|
||||
HttpGet httpGet = new HttpGet(uriString);
|
||||
addOzoneHeaders(httpGet);
|
||||
return httpGet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns httpDelete.
|
||||
*
|
||||
* @param uriString - uri
|
||||
* @return HttpDelete
|
||||
*/
|
||||
public HttpDelete getHttpDelete(String uriString) {
|
||||
HttpDelete httpDel = new HttpDelete(uriString);
|
||||
addOzoneHeaders(httpDel);
|
||||
return httpDel;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an HttpPut Object.
|
||||
*
|
||||
* @param uriString - Uri
|
||||
* @return HttpPut
|
||||
*/
|
||||
public HttpPut getHttpPut(String uriString) {
|
||||
HttpPut httpPut = new HttpPut(uriString);
|
||||
addOzoneHeaders(httpPut);
|
||||
return httpPut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Ozone Headers.
|
||||
*
|
||||
* @param httpRequest - Http Request
|
||||
*/
|
||||
private void addOzoneHeaders(HttpRequestBase httpRequest) {
|
||||
SimpleDateFormat format =
|
||||
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss ZZZ", Locale.US);
|
||||
|
||||
httpRequest.addHeader(Header.OZONE_VERSION_HEADER,
|
||||
Header.OZONE_V1_VERSION_HEADER);
|
||||
httpRequest.addHeader(HttpHeaders.DATE,
|
||||
format.format(new Date(Time.monotonicNow())));
|
||||
if (getUserAuth() != null) {
|
||||
httpRequest.addHeader(HttpHeaders.AUTHORIZATION,
|
||||
Header.OZONE_SIMPLE_AUTHENTICATION_SCHEME + " " +
|
||||
getUserAuth());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes this stream and releases any system resources associated with it. If
|
||||
* the stream is already closed then invoking this method has no effect.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// TODO : Currently we create a new HTTP client. We should switch
|
||||
// This to a Pool and cleanup the pool here.
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public CloseableHttpClient newHttpClient() {
|
||||
return HddsClientUtils.newHttpClient();
|
||||
}
|
||||
}
|
@ -1,584 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hadoop.ozone.web.client;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import org.apache.hadoop.fs.StorageType;
|
||||
import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
|
||||
import org.apache.hadoop.ozone.client.OzoneClientException;
|
||||
import org.apache.hadoop.ozone.client.rest.OzoneException;
|
||||
import org.apache.hadoop.ozone.client.rest.headers.Header;
|
||||
import org.apache.hadoop.ozone.web.request.OzoneQuota;
|
||||
import org.apache.hadoop.ozone.web.response.BucketInfo;
|
||||
import org.apache.hadoop.ozone.web.response.ListBuckets;
|
||||
import org.apache.hadoop.ozone.web.response.VolumeInfo;
|
||||
import org.apache.hadoop.ozone.OzoneConsts;
|
||||
import org.apache.hadoop.ozone.web.utils.OzoneUtils;
|
||||
|
||||
import static org.apache.hadoop.hdds.server.ServerUtils.releaseConnection;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.net.HttpURLConnection.HTTP_CREATED;
|
||||
import static java.net.HttpURLConnection.HTTP_OK;
|
||||
|
||||
/**
|
||||
* Ozone Volume Class.
|
||||
*/
|
||||
public class OzoneVolume {
|
||||
private VolumeInfo volumeInfo;
|
||||
private Map<String, String> headerMap;
|
||||
private final OzoneRestClient client;
|
||||
|
||||
/**
|
||||
* Constructor for OzoneVolume.
|
||||
*/
|
||||
public OzoneVolume(OzoneRestClient client) {
|
||||
this.client = client;
|
||||
this.headerMap = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for OzoneVolume.
|
||||
*
|
||||
* @param volInfo - volume Info.
|
||||
* @param client Client
|
||||
*/
|
||||
public OzoneVolume(VolumeInfo volInfo, OzoneRestClient client) {
|
||||
this.volumeInfo = volInfo;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Json String of this class.
|
||||
* @return String
|
||||
* @throws IOException
|
||||
*/
|
||||
public String getJsonString() throws IOException {
|
||||
return volumeInfo.toJsonString();
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the Volume Info.
|
||||
*
|
||||
* @param volInfoString - Volume Info String
|
||||
*/
|
||||
public void setVolumeInfo(String volInfoString) throws IOException {
|
||||
this.volumeInfo = VolumeInfo.parse(volInfoString);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the volume info.
|
||||
*/
|
||||
public VolumeInfo getVolumeInfo() {
|
||||
return this.volumeInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns volume Name.
|
||||
*
|
||||
* @return Volume Name.
|
||||
*/
|
||||
public String getVolumeName() {
|
||||
return this.volumeInfo.getVolumeName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get created by.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getCreatedby() {
|
||||
return this.volumeInfo.getCreatedBy();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the Owner name.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getOwnerName() {
|
||||
return this.volumeInfo.getOwner().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Quota Info.
|
||||
*
|
||||
* @return Quota
|
||||
*/
|
||||
public OzoneQuota 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.
|
||||
*
|
||||
* @param headerName - Name of the header
|
||||
* @return - Header Value
|
||||
*/
|
||||
public String getHeader(String headerName) {
|
||||
return headerMap.get(headerName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Client, this is used by Bucket and Key Classes.
|
||||
*
|
||||
* @return - Ozone Client
|
||||
*/
|
||||
OzoneRestClient getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Bucket - Creates a bucket under a given volume.
|
||||
*
|
||||
* @param bucketName - Bucket Name
|
||||
* @param acls - Acls - User Acls
|
||||
* @param storageType - Storage Class
|
||||
* @param versioning - enable versioning support on a bucket.
|
||||
*
|
||||
*
|
||||
* @return - a Ozone Bucket Object
|
||||
*/
|
||||
public OzoneBucket createBucket(String bucketName, String[] acls,
|
||||
StorageType storageType,
|
||||
OzoneConsts.Versioning versioning)
|
||||
throws OzoneException {
|
||||
|
||||
HttpPost httpPost = null;
|
||||
try (CloseableHttpClient httpClient = newHttpClient()) {
|
||||
OzoneUtils.verifyResourceName(bucketName);
|
||||
URIBuilder builder = new URIBuilder(getClient().getEndPointURI());
|
||||
builder.setPath("/" + getVolumeName() + "/" + bucketName).build();
|
||||
|
||||
httpPost = client.getHttpPost(null, builder.toString());
|
||||
if (acls != null) {
|
||||
for (String acl : acls) {
|
||||
httpPost
|
||||
.addHeader(Header.OZONE_ACLS, Header.OZONE_ACL_ADD + " " + acl);
|
||||
}
|
||||
}
|
||||
|
||||
httpPost.addHeader(Header.OZONE_STORAGE_TYPE, storageType.toString());
|
||||
httpPost.addHeader(Header.OZONE_BUCKET_VERSIONING, versioning.toString());
|
||||
executeCreateBucket(httpPost, httpClient);
|
||||
return getBucket(bucketName);
|
||||
} catch (IOException | URISyntaxException | IllegalArgumentException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
releaseConnection(httpPost);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Bucket.
|
||||
*
|
||||
* @param bucketName - bucket name
|
||||
* @param acls - acls
|
||||
* @param storageType - storage class
|
||||
*
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public OzoneBucket createBucket(String bucketName, String[] acls,
|
||||
StorageType storageType)
|
||||
throws OzoneException {
|
||||
return createBucket(bucketName, acls, storageType,
|
||||
OzoneConsts.Versioning.DISABLED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Bucket.
|
||||
*
|
||||
* @param bucketName - bucket name
|
||||
* @param acls - acls
|
||||
*
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public OzoneBucket createBucket(String bucketName, String[] acls)
|
||||
throws OzoneException {
|
||||
return createBucket(bucketName, acls, StorageType.DEFAULT,
|
||||
OzoneConsts.Versioning.DISABLED);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create Bucket.
|
||||
*
|
||||
* @param bucketName - bucket name
|
||||
*
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public OzoneBucket createBucket(String bucketName) throws OzoneException {
|
||||
return createBucket(bucketName, null, StorageType.DEFAULT,
|
||||
OzoneConsts.Versioning.DISABLED);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* execute a Create Bucket Request against Ozone server.
|
||||
*
|
||||
* @param httppost - httpPost
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws OzoneException
|
||||
*/
|
||||
private void executeCreateBucket(HttpPost httppost,
|
||||
CloseableHttpClient httpClient)
|
||||
throws IOException, OzoneException {
|
||||
HttpEntity entity = null;
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(httppost);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
entity = response.getEntity();
|
||||
if ((errorCode == HTTP_OK) || (errorCode == HTTP_CREATED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity != null) {
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
} else {
|
||||
throw new OzoneClientException("Unexpected null in http payload");
|
||||
}
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Acls to an existing bucket.
|
||||
*
|
||||
* @param bucketName - Name of the bucket
|
||||
* @param acls - Acls
|
||||
*
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public void addAcls(String bucketName, String[] acls) throws OzoneException {
|
||||
HttpPut putRequest = null;
|
||||
try (CloseableHttpClient httpClient = newHttpClient()) {
|
||||
OzoneUtils.verifyResourceName(bucketName);
|
||||
URIBuilder builder = new URIBuilder(getClient().getEndPointURI());
|
||||
builder.setPath("/" + getVolumeName() + "/" + bucketName).build();
|
||||
putRequest = client.getHttpPut(builder.toString());
|
||||
|
||||
for (String acl : acls) {
|
||||
putRequest
|
||||
.addHeader(Header.OZONE_ACLS, Header.OZONE_ACL_ADD + " " + acl);
|
||||
}
|
||||
executePutBucket(putRequest, httpClient);
|
||||
} catch (URISyntaxException | IOException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
releaseConnection(putRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes ACLs from a bucket.
|
||||
*
|
||||
* @param bucketName - Bucket Name
|
||||
* @param acls - Acls to be removed
|
||||
*
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public void removeAcls(String bucketName, String[] acls)
|
||||
throws OzoneException {
|
||||
HttpPut putRequest = null;
|
||||
try (CloseableHttpClient httpClient = newHttpClient()) {
|
||||
OzoneUtils.verifyResourceName(bucketName);
|
||||
URIBuilder builder = new URIBuilder(getClient().getEndPointURI());
|
||||
builder.setPath("/" + getVolumeName() + "/" + bucketName).build();
|
||||
putRequest = client.getHttpPut(builder.toString());
|
||||
|
||||
for (String acl : acls) {
|
||||
putRequest
|
||||
.addHeader(Header.OZONE_ACLS, Header.OZONE_ACL_REMOVE + " " + acl);
|
||||
}
|
||||
executePutBucket(putRequest, httpClient);
|
||||
} catch (URISyntaxException | IOException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
releaseConnection(putRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about an existing bucket.
|
||||
*
|
||||
* @param bucketName - BucketName
|
||||
*
|
||||
* @return OZoneBucket
|
||||
*/
|
||||
public OzoneBucket getBucket(String bucketName) throws OzoneException {
|
||||
HttpGet getRequest = null;
|
||||
try (CloseableHttpClient httpClient = newHttpClient()) {
|
||||
OzoneUtils.verifyResourceName(bucketName);
|
||||
URIBuilder builder = new URIBuilder(getClient().getEndPointURI());
|
||||
builder.setPath("/" + getVolumeName() + "/" + bucketName)
|
||||
.setParameter(Header.OZONE_INFO_QUERY_TAG,
|
||||
Header.OZONE_INFO_QUERY_BUCKET).build();
|
||||
getRequest = client.getHttpGet(builder.toString());
|
||||
return executeInfoBucket(getRequest, httpClient);
|
||||
|
||||
} catch (IOException | URISyntaxException | IllegalArgumentException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
releaseConnection(getRequest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute the info bucket call.
|
||||
*
|
||||
* @param getRequest - httpGet Request
|
||||
* @param httpClient - Http Client
|
||||
*
|
||||
* @return OzoneBucket
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws OzoneException
|
||||
*/
|
||||
private OzoneBucket executeInfoBucket(HttpGet getRequest,
|
||||
CloseableHttpClient httpClient)
|
||||
throws IOException, OzoneException {
|
||||
HttpEntity entity = null;
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(getRequest);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
entity = response.getEntity();
|
||||
if (entity == null) {
|
||||
throw new OzoneClientException("Unexpected null in http payload");
|
||||
}
|
||||
if ((errorCode == HTTP_OK) || (errorCode == HTTP_CREATED)) {
|
||||
OzoneBucket bucket =
|
||||
new OzoneBucket(BucketInfo.parse(EntityUtils.toString(entity)),
|
||||
this);
|
||||
return bucket;
|
||||
}
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the put bucket call.
|
||||
*
|
||||
* @param putRequest - http put request
|
||||
* @param httpClient - Http Client
|
||||
*
|
||||
* @return OzoneBucket
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws OzoneException
|
||||
*/
|
||||
private void executePutBucket(HttpPut putRequest,
|
||||
CloseableHttpClient httpClient)
|
||||
throws IOException, OzoneException {
|
||||
HttpEntity entity = null;
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(putRequest);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
entity = response.getEntity();
|
||||
|
||||
if (errorCode == HTTP_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity != null) {
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
}
|
||||
|
||||
throw new OzoneClientException("Unexpected null in http result");
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of buckets on this volume.
|
||||
*
|
||||
* @return - List of buckets
|
||||
*
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public List<OzoneBucket> listBuckets(String resultLength,
|
||||
String previousBucket, String prefix) throws OzoneException {
|
||||
HttpGet getRequest = null;
|
||||
try (CloseableHttpClient httpClient = newHttpClient()) {
|
||||
URIBuilder builder = new URIBuilder(getClient().getEndPointURI());
|
||||
builder.setPath("/" + getVolumeName()).build();
|
||||
if (!Strings.isNullOrEmpty(resultLength)) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_MAXKEYS, resultLength);
|
||||
}
|
||||
if (!Strings.isNullOrEmpty(previousBucket)) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_PREVKEY, previousBucket);
|
||||
}
|
||||
if (!Strings.isNullOrEmpty(prefix)) {
|
||||
builder.addParameter(Header.OZONE_LIST_QUERY_PREFIX, prefix);
|
||||
}
|
||||
|
||||
getRequest = client.getHttpGet(builder.toString());
|
||||
return executeListBuckets(getRequest, httpClient);
|
||||
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
throw new OzoneClientException(e.getMessage(), e);
|
||||
} finally {
|
||||
releaseConnection(getRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* executes the List Bucket Call.
|
||||
*
|
||||
* @param getRequest - http Request
|
||||
* @param httpClient - http Client
|
||||
*
|
||||
* @return List of OzoneBuckets
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws OzoneException
|
||||
*/
|
||||
private List<OzoneBucket> executeListBuckets(HttpGet getRequest,
|
||||
CloseableHttpClient httpClient)
|
||||
throws IOException, OzoneException {
|
||||
HttpEntity entity = null;
|
||||
List<OzoneBucket> ozoneBucketList = new LinkedList<OzoneBucket>();
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(getRequest);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
|
||||
entity = response.getEntity();
|
||||
|
||||
if (entity == null) {
|
||||
throw new OzoneClientException("Unexpected null in http payload");
|
||||
}
|
||||
if (errorCode == HTTP_OK) {
|
||||
ListBuckets bucketList =
|
||||
ListBuckets.parse(EntityUtils.toString(entity));
|
||||
|
||||
for (BucketInfo info : bucketList.getBuckets()) {
|
||||
ozoneBucketList.add(new OzoneBucket(info, this));
|
||||
}
|
||||
return ozoneBucketList;
|
||||
|
||||
} else {
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
}
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an empty bucket.
|
||||
*
|
||||
* @param bucketName - Name of the bucket to delete
|
||||
*
|
||||
* @throws OzoneException
|
||||
*/
|
||||
public void deleteBucket(String bucketName) throws OzoneException {
|
||||
HttpDelete delRequest = null;
|
||||
try (CloseableHttpClient httpClient = newHttpClient()) {
|
||||
OzoneUtils.verifyResourceName(bucketName);
|
||||
URIBuilder builder = new URIBuilder(getClient().getEndPointURI());
|
||||
builder.setPath("/" + getVolumeName() + "/" + bucketName).build();
|
||||
|
||||
delRequest = client.getHttpDelete(builder.toString());
|
||||
executeDeleteBucket(delRequest, httpClient);
|
||||
|
||||
} catch (IOException | URISyntaxException | IllegalArgumentException ex) {
|
||||
throw new OzoneClientException(ex.getMessage(), ex);
|
||||
} finally {
|
||||
releaseConnection(delRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes delete bucket call.
|
||||
*
|
||||
* @param delRequest - Delete Request
|
||||
* @param httpClient - Http Client
|
||||
7 *
|
||||
* @throws IOException
|
||||
* @throws OzoneException
|
||||
*/
|
||||
private void executeDeleteBucket(HttpDelete delRequest,
|
||||
CloseableHttpClient httpClient)
|
||||
throws IOException, OzoneException {
|
||||
HttpEntity entity = null;
|
||||
try {
|
||||
HttpResponse response = httpClient.execute(delRequest);
|
||||
int errorCode = response.getStatusLine().getStatusCode();
|
||||
entity = response.getEntity();
|
||||
|
||||
if (errorCode == HTTP_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity == null) {
|
||||
throw new OzoneClientException("Unexpected null in http payload.");
|
||||
}
|
||||
|
||||
throw OzoneException.parse(EntityUtils.toString(entity));
|
||||
|
||||
} finally {
|
||||
if (entity != null) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public CloseableHttpClient newHttpClient() {
|
||||
return HddsClientUtils.newHttpClient();
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Ozone client library is a java client for the Ozone
|
||||
* Object Store.
|
||||
*/
|
||||
package org.apache.hadoop.ozone.web.client;
|
||||
|
||||
/**
|
||||
This library is a simple Ozone REST Library.
|
||||
|
||||
This library is a very *minimal* client written for tests and
|
||||
command line utils that work against Ozone. It does not have
|
||||
things like thread-pools and support for extended security models yet.
|
||||
|
||||
OzoneClients return OzoneVolumes and OzoneVolumes return OzoneBuckets.
|
||||
**/
|
@ -37,7 +37,6 @@
|
||||
import org.apache.hadoop.ozone.ksm.KeySpaceManager;
|
||||
import org.apache.hadoop.hdds.scm.server.SCMStorage;
|
||||
import org.apache.hadoop.ozone.ksm.KSMStorage;
|
||||
import org.apache.hadoop.ozone.web.client.OzoneRestClient;
|
||||
import org.apache.hadoop.hdds.scm.ScmConfigKeys;
|
||||
import org.apache.hadoop.hdds.scm.protocolPB
|
||||
.StorageContainerLocationProtocolClientSideTranslatorPB;
|
||||
@ -167,7 +166,7 @@ public OzoneClient getRpcClient() throws IOException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link OzoneRestClient} connected to this cluster's REST
|
||||
* Creates an {@link OzoneClient} connected to this cluster's REST
|
||||
* service. Callers take ownership of the client and must close it when done.
|
||||
*
|
||||
* @return OzoneRestClient connected to this cluster's REST service
|
||||
|
@ -20,8 +20,9 @@
|
||||
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
|
||||
import org.apache.hadoop.ozone.client.protocol.ClientProtocol;
|
||||
import org.apache.hadoop.ozone.client.rpc.RpcClient;
|
||||
import org.apache.hadoop.ozone.container.ContainerTestHelper;
|
||||
import org.apache.hadoop.ozone.web.client.OzoneRestClient;
|
||||
import org.apache.hadoop.ozone.client.rest.OzoneException;
|
||||
import org.apache.ratis.rpc.RpcType;
|
||||
import org.apache.ratis.rpc.SupportedRpcType;
|
||||
@ -65,9 +66,9 @@ public MiniOzoneCluster getCluster() {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
public OzoneRestClient newOzoneRestClient()
|
||||
throws OzoneException, URISyntaxException {
|
||||
return RatisTestHelper.newOzoneRestClient(getDatanodeOzoneRestPort());
|
||||
public ClientProtocol newOzoneClient()
|
||||
throws OzoneException, URISyntaxException, IOException {
|
||||
return new RpcClient(conf);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -102,9 +103,4 @@ static MiniOzoneCluster newMiniOzoneCluster(
|
||||
.setNumDatanodes(numDatanodes).build();
|
||||
return cluster;
|
||||
}
|
||||
|
||||
static OzoneRestClient newOzoneRestClient(int port)
|
||||
throws OzoneException, URISyntaxException {
|
||||
return new OzoneRestClient("http://localhost:" + port);
|
||||
}
|
||||
}
|
||||
|
@ -23,23 +23,31 @@
|
||||
import static org.apache.hadoop.ozone.OzoneConsts.CHUNK_SIZE;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.RandomStringUtils;
|
||||
import org.apache.hadoop.ozone.OzoneConsts;
|
||||
import org.apache.hadoop.ozone.web.client.OzoneRestClient;
|
||||
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.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.client.OzoneVolume;
|
||||
import org.apache.hadoop.ozone.client.OzoneBucket;
|
||||
import org.apache.hadoop.ozone.client.rpc.RpcClient;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.apache.hadoop.io.IOUtils;
|
||||
import org.apache.hadoop.ozone.MiniOzoneCluster;
|
||||
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
|
||||
import org.apache.hadoop.ozone.web.client.OzoneBucket;
|
||||
import org.apache.hadoop.ozone.web.client.OzoneVolume;
|
||||
import org.apache.hadoop.ozone.web.request.OzoneQuota;
|
||||
import org.junit.rules.Timeout;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* End-to-end testing of Ozone REST operations.
|
||||
*/
|
||||
@ -52,7 +60,9 @@ public class TestOzoneRestWithMiniCluster {
|
||||
|
||||
private static MiniOzoneCluster cluster;
|
||||
private static OzoneConfiguration conf;
|
||||
private static OzoneRestClient ozoneClient;
|
||||
private static ClientProtocol client;
|
||||
private static ReplicationFactor replicationFactor = ReplicationFactor.ONE;
|
||||
private static ReplicationType replicationType = ReplicationType.STAND_ALONE;
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
@ -62,180 +72,125 @@ public static void init() throws Exception {
|
||||
conf = new OzoneConfiguration();
|
||||
cluster = MiniOzoneCluster.newBuilder(conf).build();
|
||||
cluster.waitForClusterToBeReady();
|
||||
int port = cluster.getHddsDatanodes().get(0)
|
||||
.getDatanodeDetails().getOzoneRestPort();
|
||||
ozoneClient = new OzoneRestClient(
|
||||
String.format("http://localhost:%d", port));
|
||||
ozoneClient.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER);
|
||||
client = new RpcClient(conf);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void shutdown() throws InterruptedException {
|
||||
public static void shutdown() throws InterruptedException, IOException {
|
||||
if (cluster != null) {
|
||||
cluster.shutdown();
|
||||
}
|
||||
IOUtils.cleanupWithLogger(null, ozoneClient);
|
||||
client.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndGetVolume() throws Exception {
|
||||
String volumeName = nextId("volume");
|
||||
OzoneVolume volume = ozoneClient.createVolume(volumeName, "bilbo", "100TB");
|
||||
assertNotNull(volume);
|
||||
assertEquals(volumeName, volume.getVolumeName());
|
||||
assertEquals(ozoneClient.getUserAuth(), volume.getCreatedby());
|
||||
assertEquals("bilbo", volume.getOwnerName());
|
||||
assertNotNull(volume.getQuota());
|
||||
assertEquals(OzoneQuota.parseQuota("100TB").sizeInBytes(),
|
||||
volume.getQuota().sizeInBytes());
|
||||
volume = ozoneClient.getVolume(volumeName);
|
||||
assertNotNull(volume);
|
||||
assertEquals(volumeName, volume.getVolumeName());
|
||||
assertEquals(ozoneClient.getUserAuth(), volume.getCreatedby());
|
||||
assertEquals("bilbo", volume.getOwnerName());
|
||||
assertNotNull(volume.getQuota());
|
||||
assertEquals(OzoneQuota.parseQuota("100TB").sizeInBytes(),
|
||||
volume.getQuota().sizeInBytes());
|
||||
createAndGetVolume();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndGetBucket() throws Exception {
|
||||
String volumeName = nextId("volume");
|
||||
String bucketName = nextId("bucket");
|
||||
OzoneVolume volume = ozoneClient.createVolume(volumeName, "bilbo", "100TB");
|
||||
assertNotNull(volume);
|
||||
assertEquals(volumeName, volume.getVolumeName());
|
||||
assertEquals(ozoneClient.getUserAuth(), volume.getCreatedby());
|
||||
assertEquals("bilbo", volume.getOwnerName());
|
||||
assertNotNull(volume.getQuota());
|
||||
assertEquals(OzoneQuota.parseQuota("100TB").sizeInBytes(),
|
||||
volume.getQuota().sizeInBytes());
|
||||
OzoneBucket bucket = volume.createBucket(bucketName);
|
||||
assertNotNull(bucket);
|
||||
assertEquals(bucketName, bucket.getBucketName());
|
||||
bucket = volume.getBucket(bucketName);
|
||||
assertNotNull(bucket);
|
||||
assertEquals(bucketName, bucket.getBucketName());
|
||||
OzoneVolume volume = createAndGetVolume();
|
||||
createAndGetBucket(volume);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutAndGetKey() throws Exception {
|
||||
String volumeName = nextId("volume");
|
||||
String bucketName = nextId("bucket");
|
||||
String keyName = nextId("key");
|
||||
String keyData = nextId("data");
|
||||
OzoneVolume volume = ozoneClient.createVolume(volumeName, "bilbo", "100TB");
|
||||
assertNotNull(volume);
|
||||
assertEquals(volumeName, volume.getVolumeName());
|
||||
assertEquals(ozoneClient.getUserAuth(), volume.getCreatedby());
|
||||
assertEquals("bilbo", volume.getOwnerName());
|
||||
assertNotNull(volume.getQuota());
|
||||
assertEquals(OzoneQuota.parseQuota("100TB").sizeInBytes(),
|
||||
volume.getQuota().sizeInBytes());
|
||||
OzoneBucket bucket = volume.createBucket(bucketName);
|
||||
assertNotNull(bucket);
|
||||
assertEquals(bucketName, bucket.getBucketName());
|
||||
bucket.putKey(keyName, keyData);
|
||||
assertEquals(keyData, bucket.getKey(keyName));
|
||||
OzoneVolume volume = createAndGetVolume();
|
||||
OzoneBucket bucket = createAndGetBucket(volume);
|
||||
putKey(bucket, keyName, keyData);
|
||||
}
|
||||
|
||||
private void putKey(OzoneBucket bucket, String keyName, String keyData) throws IOException {
|
||||
try (
|
||||
OzoneOutputStream ozoneOutputStream = bucket
|
||||
.createKey(keyName, 0, replicationType, replicationFactor);
|
||||
InputStream inputStream = IOUtils.toInputStream(keyData, UTF_8)) {
|
||||
IOUtils.copy(inputStream, ozoneOutputStream);
|
||||
}
|
||||
try (
|
||||
InputStream inputStream = IOUtils.toInputStream(keyData, UTF_8);
|
||||
OzoneInputStream ozoneInputStream = bucket.readKey(keyName)) {
|
||||
IOUtils.contentEquals(ozoneInputStream, inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutAndGetEmptyKey() throws Exception {
|
||||
String volumeName = nextId("volume");
|
||||
String bucketName = nextId("bucket");
|
||||
String keyName = nextId("key");
|
||||
String keyData = "";
|
||||
OzoneVolume volume = ozoneClient.createVolume(volumeName, "bilbo", "100TB");
|
||||
assertNotNull(volume);
|
||||
assertEquals(volumeName, volume.getVolumeName());
|
||||
assertEquals(ozoneClient.getUserAuth(), volume.getCreatedby());
|
||||
assertEquals("bilbo", volume.getOwnerName());
|
||||
assertNotNull(volume.getQuota());
|
||||
assertEquals(OzoneQuota.parseQuota("100TB").sizeInBytes(),
|
||||
volume.getQuota().sizeInBytes());
|
||||
OzoneBucket bucket = volume.createBucket(bucketName);
|
||||
assertNotNull(bucket);
|
||||
assertEquals(bucketName, bucket.getBucketName());
|
||||
bucket.putKey(keyName, keyData);
|
||||
assertEquals(keyData, bucket.getKey(keyName));
|
||||
OzoneVolume volume = createAndGetVolume();
|
||||
OzoneBucket bucket = createAndGetBucket(volume);
|
||||
putKey(bucket, keyName, keyData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutAndGetMultiChunkKey() throws Exception {
|
||||
String volumeName = nextId("volume");
|
||||
String bucketName = nextId("bucket");
|
||||
String keyName = nextId("key");
|
||||
int keyDataLen = 3 * CHUNK_SIZE;
|
||||
String keyData = buildKeyData(keyDataLen);
|
||||
OzoneVolume volume = ozoneClient.createVolume(volumeName, "bilbo", "100TB");
|
||||
assertNotNull(volume);
|
||||
assertEquals(volumeName, volume.getVolumeName());
|
||||
assertEquals(ozoneClient.getUserAuth(), volume.getCreatedby());
|
||||
assertEquals("bilbo", volume.getOwnerName());
|
||||
assertNotNull(volume.getQuota());
|
||||
assertEquals(OzoneQuota.parseQuota("100TB").sizeInBytes(),
|
||||
volume.getQuota().sizeInBytes());
|
||||
OzoneBucket bucket = volume.createBucket(bucketName);
|
||||
assertNotNull(bucket);
|
||||
assertEquals(bucketName, bucket.getBucketName());
|
||||
bucket.putKey(keyName, keyData);
|
||||
assertEquals(keyData, bucket.getKey(keyName));
|
||||
OzoneVolume volume = createAndGetVolume();
|
||||
OzoneBucket bucket = createAndGetBucket(volume);
|
||||
putKey(bucket, keyName, keyData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutAndGetMultiChunkKeyLastChunkPartial() throws Exception {
|
||||
String volumeName = nextId("volume");
|
||||
String bucketName = nextId("bucket");
|
||||
String keyName = nextId("key");
|
||||
int keyDataLen = (int)(2.5 * CHUNK_SIZE);
|
||||
String keyData = buildKeyData(keyDataLen);
|
||||
OzoneVolume volume = ozoneClient.createVolume(volumeName, "bilbo", "100TB");
|
||||
assertNotNull(volume);
|
||||
assertEquals(volumeName, volume.getVolumeName());
|
||||
assertEquals(ozoneClient.getUserAuth(), volume.getCreatedby());
|
||||
assertEquals("bilbo", volume.getOwnerName());
|
||||
assertNotNull(volume.getQuota());
|
||||
assertEquals(OzoneQuota.parseQuota("100TB").sizeInBytes(),
|
||||
volume.getQuota().sizeInBytes());
|
||||
OzoneBucket bucket = volume.createBucket(bucketName);
|
||||
assertNotNull(bucket);
|
||||
assertEquals(bucketName, bucket.getBucketName());
|
||||
bucket.putKey(keyName, keyData);
|
||||
assertEquals(keyData, bucket.getKey(keyName));
|
||||
OzoneVolume volume = createAndGetVolume();
|
||||
OzoneBucket bucket = createAndGetBucket(volume);
|
||||
putKey(bucket, keyName, keyData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceKey() throws Exception {
|
||||
String volumeName = nextId("volume");
|
||||
String bucketName = nextId("bucket");
|
||||
String keyName = nextId("key");
|
||||
int keyDataLen = (int)(2.5 * CHUNK_SIZE);
|
||||
String keyData = buildKeyData(keyDataLen);
|
||||
OzoneVolume volume = ozoneClient.createVolume(volumeName, "bilbo", "100TB");
|
||||
assertNotNull(volume);
|
||||
assertEquals(volumeName, volume.getVolumeName());
|
||||
assertEquals(ozoneClient.getUserAuth(), volume.getCreatedby());
|
||||
assertEquals("bilbo", volume.getOwnerName());
|
||||
assertNotNull(volume.getQuota());
|
||||
assertEquals(OzoneQuota.parseQuota("100TB").sizeInBytes(),
|
||||
volume.getQuota().sizeInBytes());
|
||||
OzoneBucket bucket = volume.createBucket(bucketName);
|
||||
assertNotNull(bucket);
|
||||
assertEquals(bucketName, bucket.getBucketName());
|
||||
bucket.putKey(keyName, keyData);
|
||||
assertEquals(keyData, bucket.getKey(keyName));
|
||||
OzoneVolume volume = createAndGetVolume();
|
||||
OzoneBucket bucket = createAndGetBucket(volume);
|
||||
putKey(bucket, keyName, keyData);
|
||||
|
||||
// Replace key with data consisting of fewer chunks.
|
||||
keyDataLen = (int)(1.5 * CHUNK_SIZE);
|
||||
keyData = buildKeyData(keyDataLen);
|
||||
bucket.putKey(keyName, keyData);
|
||||
assertEquals(keyData, bucket.getKey(keyName));
|
||||
putKey(bucket, keyName, keyData);
|
||||
|
||||
// Replace key with data consisting of more chunks.
|
||||
keyDataLen = (int)(3.5 * CHUNK_SIZE);
|
||||
keyData = buildKeyData(keyDataLen);
|
||||
bucket.putKey(keyName, keyData);
|
||||
assertEquals(keyData, bucket.getKey(keyName));
|
||||
putKey(bucket, keyName, keyData);
|
||||
}
|
||||
|
||||
private OzoneVolume createAndGetVolume() throws IOException {
|
||||
String volumeName = nextId("volume");
|
||||
VolumeArgs volumeArgs = VolumeArgs.newBuilder()
|
||||
.setOwner("bilbo")
|
||||
.setQuota("100TB")
|
||||
.setAdmin("hdfs")
|
||||
.build();
|
||||
client.createVolume(volumeName, volumeArgs);
|
||||
OzoneVolume volume = client.getVolumeDetails(volumeName);
|
||||
assertEquals(volumeName, volume.getName());
|
||||
assertNotNull(volume);
|
||||
assertEquals("bilbo", volume.getOwner());
|
||||
assertNotNull(volume.getQuota());
|
||||
assertEquals(OzoneQuota.parseQuota("100TB").sizeInBytes(),
|
||||
volume.getQuota());
|
||||
return volume;
|
||||
}
|
||||
|
||||
private OzoneBucket createAndGetBucket(OzoneVolume vol) throws IOException {
|
||||
String bucketName = nextId("bucket");
|
||||
vol.createBucket(bucketName);
|
||||
OzoneBucket bucket = vol.getBucket(bucketName);
|
||||
assertNotNull(bucket);
|
||||
assertEquals(bucketName, bucket.getName());
|
||||
return bucket;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,12 +17,17 @@
|
||||
*/
|
||||
package org.apache.hadoop.ozone.web.client;
|
||||
|
||||
import org.apache.hadoop.fs.StorageType;
|
||||
import org.apache.hadoop.ozone.MiniOzoneCluster;
|
||||
import org.apache.hadoop.ozone.OzoneAcl;
|
||||
import org.apache.hadoop.ozone.OzoneConfigKeys;
|
||||
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
|
||||
import org.apache.hadoop.ozone.client.OzoneClientException;
|
||||
import org.apache.hadoop.ozone.client.BucketArgs;
|
||||
import org.apache.hadoop.ozone.client.VolumeArgs;
|
||||
import org.apache.hadoop.ozone.client.protocol.ClientProtocol;
|
||||
import org.apache.hadoop.ozone.client.OzoneVolume;
|
||||
import org.apache.hadoop.ozone.client.OzoneBucket;
|
||||
import org.apache.hadoop.ozone.client.rest.OzoneException;
|
||||
import org.apache.hadoop.ozone.client.rpc.RpcClient;
|
||||
import org.apache.hadoop.ozone.web.request.OzoneQuota;
|
||||
import org.apache.hadoop.ozone.web.utils.OzoneUtils;
|
||||
import org.apache.hadoop.test.GenericTestUtils;
|
||||
@ -36,7 +41,10 @@
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.text.ParseException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@ -54,7 +62,7 @@ public class TestBuckets {
|
||||
public Timeout testTimeout = new Timeout(300000);
|
||||
|
||||
private static MiniOzoneCluster cluster = null;
|
||||
private static OzoneRestClient ozoneRestClient = null;
|
||||
private static ClientProtocol client = null;
|
||||
|
||||
/**
|
||||
* Create a MiniDFSCluster for testing.
|
||||
@ -76,11 +84,10 @@ public static void init() throws IOException,
|
||||
OzoneConfigKeys.OZONE_LOCALSTORAGE_ROOT_DEFAULT);
|
||||
|
||||
conf.set(OzoneConfigKeys.OZONE_LOCALSTORAGE_ROOT, path);
|
||||
cluster = MiniOzoneCluster.newBuilder(conf).build();
|
||||
final int port = cluster.getHddsDatanodes().get(0).getDatanodeDetails()
|
||||
.getOzoneRestPort();
|
||||
ozoneRestClient = new OzoneRestClient(
|
||||
String.format("http://localhost:%d", port));
|
||||
cluster = MiniOzoneCluster.newBuilder(conf)
|
||||
.setNumDatanodes(3)
|
||||
.build();
|
||||
client = new RpcClient(conf);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -95,110 +102,151 @@ public static void shutdown() {
|
||||
|
||||
@Test
|
||||
public void testCreateBucket() throws Exception {
|
||||
runTestCreateBucket(ozoneRestClient);
|
||||
runTestCreateBucket(client);
|
||||
}
|
||||
|
||||
static void runTestCreateBucket(OzoneRestClient client)
|
||||
static void runTestCreateBucket(ClientProtocol client)
|
||||
throws OzoneException, IOException, ParseException {
|
||||
String volumeName = OzoneUtils.getRequestID().toLowerCase();
|
||||
client.setUserAuth("hdfs");
|
||||
OzoneVolume vol = client.createVolume(volumeName, "bilbo", "100TB");
|
||||
VolumeArgs volumeArgs = VolumeArgs.newBuilder()
|
||||
.setOwner("bilbo")
|
||||
.setQuota("100TB")
|
||||
.setAdmin("hdfs")
|
||||
.build();
|
||||
client.createVolume(volumeName, volumeArgs);
|
||||
OzoneVolume vol = client.getVolumeDetails(volumeName);
|
||||
String[] acls = {"user:frodo:rw", "user:samwise:rw"};
|
||||
|
||||
// create 10 buckets under same volume
|
||||
for (int x = 0; x < 10; x++) {
|
||||
long currentTime = Time.now();
|
||||
String bucketName = OzoneUtils.getRequestID().toLowerCase();
|
||||
OzoneBucket bucket =
|
||||
vol.createBucket(bucketName, acls, StorageType.DEFAULT);
|
||||
assertEquals(bucket.getBucketName(), bucketName);
|
||||
|
||||
List<OzoneAcl> aclList =
|
||||
Arrays.stream(acls).map(acl -> OzoneAcl.parseAcl(acl))
|
||||
.collect(Collectors.toList());
|
||||
BucketArgs bucketArgs = BucketArgs.newBuilder()
|
||||
.setAcls(aclList)
|
||||
.build();
|
||||
vol.createBucket(bucketName, bucketArgs);
|
||||
OzoneBucket bucket = vol.getBucket(bucketName);
|
||||
assertEquals(bucket.getName(), bucketName);
|
||||
|
||||
// verify the bucket creation time
|
||||
assertTrue((OzoneUtils.formatDate(bucket.getCreatedOn())
|
||||
/ 1000) >= (currentTime / 1000));
|
||||
assertTrue((bucket.getCreationTime() / 1000) >= (currentTime / 1000));
|
||||
}
|
||||
client.close();
|
||||
|
||||
assertEquals(vol.getVolumeName(), volumeName);
|
||||
assertEquals(vol.getCreatedby(), "hdfs");
|
||||
assertEquals(vol.getOwnerName(), "bilbo");
|
||||
assertEquals(vol.getQuota().getUnit(), OzoneQuota.Units.TB);
|
||||
assertEquals(vol.getQuota().getSize(), 100);
|
||||
assertEquals(vol.getName(), volumeName);
|
||||
assertEquals(vol.getAdmin(), "hdfs");
|
||||
assertEquals(vol.getOwner(), "bilbo");
|
||||
assertEquals(vol.getQuota(), OzoneQuota.parseQuota("100TB").sizeInBytes());
|
||||
|
||||
// Test create a bucket with invalid bucket name,
|
||||
// not use Rule here because the test method is static.
|
||||
try {
|
||||
String invalidBucketName = "#" + OzoneUtils.getRequestID().toLowerCase();
|
||||
vol.createBucket(invalidBucketName, acls, StorageType.DEFAULT);
|
||||
vol.createBucket(invalidBucketName);
|
||||
fail("Except the bucket creation to be failed because the"
|
||||
+ " bucket name starts with an invalid char #");
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof OzoneClientException);
|
||||
assertTrue(e.getMessage().contains("Bucket or Volume name"
|
||||
+ " has an unsupported character : #"));
|
||||
assertTrue(e.getMessage()
|
||||
.contains("Bucket or Volume name has an unsupported character : #"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddBucketAcls() throws Exception {
|
||||
runTestAddBucketAcls(ozoneRestClient);
|
||||
runTestAddBucketAcls(client);
|
||||
}
|
||||
|
||||
static void runTestAddBucketAcls(OzoneRestClient client)
|
||||
static void runTestAddBucketAcls(ClientProtocol client)
|
||||
throws OzoneException, IOException, ParseException {
|
||||
String volumeName = OzoneUtils.getRequestID().toLowerCase();
|
||||
client.setUserAuth("hdfs");
|
||||
OzoneVolume vol = client.createVolume(volumeName, "bilbo", "100TB");
|
||||
VolumeArgs volumeArgs = VolumeArgs.newBuilder()
|
||||
.setOwner("bilbo")
|
||||
.setQuota("100TB")
|
||||
.setAdmin("hdfs")
|
||||
.build();
|
||||
client.createVolume(volumeName, volumeArgs);
|
||||
OzoneVolume vol = client.getVolumeDetails(volumeName);
|
||||
String[] acls = {"user:frodo:rw", "user:samwise:rw"};
|
||||
String bucketName = OzoneUtils.getRequestID().toLowerCase();
|
||||
vol.createBucket(bucketName);
|
||||
vol.addAcls(bucketName, acls);
|
||||
OzoneBucket bucket = vol.getBucket(bucketName);
|
||||
List<OzoneAcl> aclList =
|
||||
Arrays.stream(acls).map(acl -> OzoneAcl.parseAcl(acl))
|
||||
.collect(Collectors.toList());
|
||||
int numAcls = bucket.getAcls().size();
|
||||
bucket.addAcls(aclList);
|
||||
OzoneBucket updatedBucket = vol.getBucket(bucketName);
|
||||
assertEquals(updatedBucket.getAcls().size(), 2);
|
||||
assertEquals(updatedBucket.getAcls().size(), 2 + numAcls);
|
||||
// verify if the creation time is missing after update operation
|
||||
assertTrue(
|
||||
(OzoneUtils.formatDate(updatedBucket.getCreatedOn()) / 1000) >= 0);
|
||||
(updatedBucket.getCreationTime()) / 1000 >= 0);
|
||||
client.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveBucketAcls() throws Exception {
|
||||
runTestRemoveBucketAcls(ozoneRestClient);
|
||||
runTestRemoveBucketAcls(client);
|
||||
}
|
||||
|
||||
static void runTestRemoveBucketAcls(OzoneRestClient client)
|
||||
static void runTestRemoveBucketAcls(ClientProtocol client)
|
||||
throws OzoneException, IOException, ParseException {
|
||||
String volumeName = OzoneUtils.getRequestID().toLowerCase();
|
||||
client.setUserAuth("hdfs");
|
||||
OzoneVolume vol = client.createVolume(volumeName, "bilbo", "100TB");
|
||||
VolumeArgs volumeArgs = VolumeArgs.newBuilder()
|
||||
.setOwner("bilbo")
|
||||
.setQuota("100TB")
|
||||
.setAdmin("hdfs")
|
||||
.build();
|
||||
client.createVolume(volumeName, volumeArgs);
|
||||
OzoneVolume vol = client.getVolumeDetails(volumeName);
|
||||
String[] acls = {"user:frodo:rw", "user:samwise:rw"};
|
||||
String bucketName = OzoneUtils.getRequestID().toLowerCase();
|
||||
OzoneBucket bucket = vol.createBucket(bucketName, acls);
|
||||
assertEquals(bucket.getAcls().size(), 2);
|
||||
vol.removeAcls(bucketName, acls);
|
||||
List<OzoneAcl> aclList =
|
||||
Arrays.stream(acls).map(acl -> OzoneAcl.parseAcl(acl))
|
||||
.collect(Collectors.toList());
|
||||
vol.createBucket(bucketName);
|
||||
OzoneBucket bucket = vol.getBucket(bucketName);
|
||||
int numAcls = bucket.getAcls().size();
|
||||
bucket.addAcls(aclList);
|
||||
assertEquals(bucket.getAcls().size(), 2 + numAcls);
|
||||
bucket.removeAcls(aclList);
|
||||
OzoneBucket updatedBucket = vol.getBucket(bucketName);
|
||||
|
||||
// We removed all acls
|
||||
assertEquals(updatedBucket.getAcls().size(), 0);
|
||||
assertEquals(updatedBucket.getAcls().size(), numAcls);
|
||||
// verify if the creation time is missing after update operation
|
||||
assertTrue(
|
||||
(OzoneUtils.formatDate(updatedBucket.getCreatedOn()) / 1000) >= 0);
|
||||
(updatedBucket.getCreationTime() / 1000) >= 0);
|
||||
client.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteBucket() throws OzoneException, IOException {
|
||||
runTestDeleteBucket(ozoneRestClient);
|
||||
runTestDeleteBucket(client);
|
||||
}
|
||||
|
||||
static void runTestDeleteBucket(OzoneRestClient client)
|
||||
static void runTestDeleteBucket(ClientProtocol client)
|
||||
throws OzoneException, IOException {
|
||||
String volumeName = OzoneUtils.getRequestID().toLowerCase();
|
||||
client.setUserAuth("hdfs");
|
||||
OzoneVolume vol = client.createVolume(volumeName, "bilbo", "100TB");
|
||||
VolumeArgs volumeArgs = VolumeArgs.newBuilder()
|
||||
.setOwner("bilbo")
|
||||
.setQuota("100TB")
|
||||
.setAdmin("hdfs")
|
||||
.build();
|
||||
client.createVolume(volumeName, volumeArgs);
|
||||
OzoneVolume vol = client.getVolumeDetails(volumeName);
|
||||
String[] acls = {"user:frodo:rw", "user:samwise:rw"};
|
||||
String bucketName = OzoneUtils.getRequestID().toLowerCase();
|
||||
vol.createBucket(bucketName, acls);
|
||||
List<OzoneAcl> aclList =
|
||||
Arrays.stream(acls).map(acl -> OzoneAcl.parseAcl(acl))
|
||||
.collect(Collectors.toList());
|
||||
BucketArgs bucketArgs = BucketArgs.newBuilder()
|
||||
.setAcls(aclList)
|
||||
.build();
|
||||
vol.createBucket(bucketName, bucketArgs);
|
||||
vol.deleteBucket(bucketName);
|
||||
try {
|
||||
OzoneBucket updatedBucket = vol.getBucket(bucketName);
|
||||
@ -212,38 +260,57 @@ static void runTestDeleteBucket(OzoneRestClient client)
|
||||
|
||||
@Test
|
||||
public void testListBucket() throws Exception {
|
||||
runTestListBucket(ozoneRestClient);
|
||||
runTestListBucket(client);
|
||||
}
|
||||
|
||||
static void runTestListBucket(OzoneRestClient client)
|
||||
static void runTestListBucket(ClientProtocol client)
|
||||
throws OzoneException, IOException, ParseException {
|
||||
String volumeName = OzoneUtils.getRequestID().toLowerCase();
|
||||
client.setUserAuth("hdfs");
|
||||
OzoneVolume vol = client.createVolume(volumeName, "bilbo", "100TB");
|
||||
VolumeArgs volumeArgs = VolumeArgs.newBuilder()
|
||||
.setOwner("bilbo")
|
||||
.setQuota("100TB")
|
||||
.setAdmin("hdfs")
|
||||
.build();
|
||||
client.createVolume(volumeName, volumeArgs);
|
||||
OzoneVolume vol = client.getVolumeDetails(volumeName);
|
||||
String[] acls = {"user:frodo:rw", "user:samwise:rw"};
|
||||
List<OzoneAcl> aclList =
|
||||
Arrays.stream(acls).map(acl -> OzoneAcl.parseAcl(acl))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
long currentTime = Time.now();
|
||||
for (int x = 0; x < 10; x++) {
|
||||
String bucketName = "listbucket-test-" + x;
|
||||
vol.createBucket(bucketName, acls);
|
||||
BucketArgs bucketArgs = BucketArgs.newBuilder()
|
||||
.setAcls(aclList)
|
||||
.build();
|
||||
vol.createBucket(bucketName, bucketArgs);
|
||||
}
|
||||
List<OzoneBucket> bucketList = vol.listBuckets("100", null, null);
|
||||
assertEquals(bucketList.size(), 10);
|
||||
Iterator<OzoneBucket> bucketIterator = vol.listBuckets(null);
|
||||
int count = 0;
|
||||
|
||||
for (OzoneBucket bucket : bucketList) {
|
||||
assertTrue((OzoneUtils.formatDate(bucket.getCreatedOn())
|
||||
while (bucketIterator.hasNext()) {
|
||||
assertTrue((bucketIterator.next().getCreationTime()
|
||||
/ 1000) >= (currentTime / 1000));
|
||||
count++;
|
||||
}
|
||||
assertEquals(count, 10);
|
||||
|
||||
bucketList = vol.listBuckets("3", null, null);
|
||||
assertEquals(bucketList.size(), 3);
|
||||
bucketIterator = vol.listBuckets(null, "listbucket-test-4");
|
||||
assertEquals(getSize(bucketIterator), 5);
|
||||
|
||||
bucketList = vol.listBuckets("100", "listbucket-test-4", null);
|
||||
assertEquals(bucketList.size(), 5);
|
||||
|
||||
bucketList = vol.listBuckets("100", null, "listbucket-test-3");
|
||||
assertEquals(bucketList.size(), 1);
|
||||
bucketIterator = vol.listBuckets(null, "listbucket-test-3");
|
||||
assertEquals(getSize(bucketIterator), 6);
|
||||
|
||||
client.close();
|
||||
}
|
||||
|
||||
private static int getSize(Iterator<OzoneBucket> bucketIterator) {
|
||||
int count = 0;
|
||||
while (bucketIterator.hasNext()) {
|
||||
count++;
|
||||
bucketIterator.next();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
package org.apache.hadoop.ozone.web.client;
|
||||
|
||||
import org.apache.hadoop.ozone.RatisTestHelper;
|
||||
import org.apache.hadoop.ozone.client.protocol.ClientProtocol;
|
||||
import org.apache.hadoop.ozone.client.rest.OzoneException;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
@ -35,12 +36,12 @@ public class TestBucketsRatis {
|
||||
public Timeout testTimeout = new Timeout(300000);
|
||||
|
||||
private static RatisTestHelper.RatisTestSuite suite;
|
||||
private static OzoneRestClient ozoneRestClient;
|
||||
private static ClientProtocol client;
|
||||
|
||||
@BeforeClass
|
||||
public static void init() throws Exception {
|
||||
suite = new RatisTestHelper.RatisTestSuite(TestBucketsRatis.class);
|
||||
ozoneRestClient = suite.newOzoneRestClient();
|
||||
client = suite.newOzoneClient();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@ -52,25 +53,25 @@ public static void shutdown() {
|
||||
|
||||
@Test
|
||||
public void testCreateBucket() throws Exception {
|
||||
TestBuckets.runTestCreateBucket(ozoneRestClient);
|
||||
TestBuckets.runTestCreateBucket(client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddBucketAcls() throws Exception {
|
||||
TestBuckets.runTestAddBucketAcls(ozoneRestClient);
|
||||
TestBuckets.runTestAddBucketAcls(client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveBucketAcls() throws Exception {
|
||||
TestBuckets.runTestRemoveBucketAcls(ozoneRestClient);
|
||||
TestBuckets.runTestRemoveBucketAcls(client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteBucket() throws OzoneException, IOException {
|
||||
TestBuckets.runTestDeleteBucket(ozoneRestClient);
|
||||
TestBuckets.runTestDeleteBucket(client);
|
||||
}
|
||||
@Test
|
||||
public void testListBucket() throws Exception {
|
||||
TestBuckets.runTestListBucket(ozoneRestClient);
|
||||
TestBuckets.runTestListBucket(client);
|
||||
}
|
||||
}
|
||||
|
@ -20,16 +20,29 @@
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.collections.IteratorUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.RandomStringUtils;
|
||||
import org.apache.commons.lang.math.RandomUtils;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.hadoop.fs.StorageType;
|
||||
import org.apache.hadoop.hdds.client.ReplicationFactor;
|
||||
import org.apache.hadoop.hdds.client.ReplicationType;
|
||||
import org.apache.hadoop.ozone.MiniOzoneCluster;
|
||||
import org.apache.hadoop.ozone.OzoneAcl;
|
||||
import org.apache.hadoop.ozone.OzoneConfigKeys;
|
||||
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
|
||||
import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
|
||||
import org.apache.hadoop.ozone.client.BucketArgs;
|
||||
import org.apache.hadoop.ozone.client.VolumeArgs;
|
||||
import org.apache.hadoop.ozone.client.OzoneBucket;
|
||||
import org.apache.hadoop.ozone.client.OzoneKey;
|
||||
import org.apache.hadoop.ozone.client.OzoneVolume;
|
||||
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.client.rpc.RpcClient;
|
||||
import org.apache.hadoop.ozone.container.common.helpers.ContainerData;
|
||||
import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils;
|
||||
import org.apache.hadoop.ozone.container.common.helpers.KeyData;
|
||||
@ -59,15 +72,18 @@
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@ -84,10 +100,13 @@ public class TestKeys {
|
||||
@Rule
|
||||
public Timeout testTimeout = new Timeout(300000);
|
||||
|
||||
private static OzoneConfiguration conf;
|
||||
private static MiniOzoneCluster ozoneCluster = null;
|
||||
private static String path;
|
||||
private static OzoneRestClient ozoneRestClient = null;
|
||||
private static ClientProtocol client = null;
|
||||
private static long currentTime;
|
||||
private static ReplicationFactor replicationFactor = ReplicationFactor.ONE;
|
||||
private static ReplicationType replicationType = ReplicationType.STAND_ALONE;
|
||||
|
||||
/**
|
||||
* Create a MiniDFSCluster for testing.
|
||||
@ -96,7 +115,7 @@ public class TestKeys {
|
||||
*/
|
||||
@BeforeClass
|
||||
public static void init() throws Exception {
|
||||
OzoneConfiguration conf = new OzoneConfiguration();
|
||||
conf = new OzoneConfiguration();
|
||||
|
||||
// Set short block deleting service interval to speed up deletions.
|
||||
conf.setTimeDuration(OzoneConfigKeys.OZONE_BLOCK_DELETING_SERVICE_INTERVAL,
|
||||
@ -105,12 +124,9 @@ public static void init() throws Exception {
|
||||
path = GenericTestUtils.getTempPath(TestKeys.class.getSimpleName());
|
||||
Logger.getLogger("log4j.logger.org.apache.http").setLevel(Level.DEBUG);
|
||||
|
||||
ozoneCluster = MiniOzoneCluster.newBuilder(conf).build();
|
||||
ozoneCluster = MiniOzoneCluster.newBuilder(conf).setNumDatanodes(1).build();
|
||||
ozoneCluster.waitForClusterToBeReady();
|
||||
final int port = ozoneCluster.getHddsDatanodes().get(0)
|
||||
.getDatanodeDetails().getOzoneRestPort();
|
||||
ozoneRestClient = new OzoneRestClient(
|
||||
String.format("http://localhost:%d", port));
|
||||
client = new RpcClient(conf);
|
||||
currentTime = Time.now();
|
||||
}
|
||||
|
||||
@ -166,7 +182,7 @@ static String getMultiPartKey(String delimiter) {
|
||||
}
|
||||
|
||||
static class PutHelper {
|
||||
private final OzoneRestClient client;
|
||||
private final ClientProtocol client;
|
||||
private final String dir;
|
||||
private final String keyName;
|
||||
|
||||
@ -174,11 +190,11 @@ static class PutHelper {
|
||||
private OzoneBucket bucket;
|
||||
private File file;
|
||||
|
||||
PutHelper(OzoneRestClient client, String dir) {
|
||||
PutHelper(ClientProtocol client, String dir) {
|
||||
this(client, dir, OzoneUtils.getRequestID().toLowerCase());
|
||||
}
|
||||
|
||||
PutHelper(OzoneRestClient client, String dir, String key) {
|
||||
PutHelper(ClientProtocol client, String dir, String key) {
|
||||
this.client = client;
|
||||
this.dir = dir;
|
||||
this.keyName = key;
|
||||
@ -202,111 +218,139 @@ public File getFile() {
|
||||
* @return Returns the name of the new key that was created.
|
||||
* @throws OzoneException
|
||||
*/
|
||||
private KsmKeyArgs putKey() throws Exception {
|
||||
private String putKey() throws Exception {
|
||||
String volumeName = OzoneUtils.getRequestID().toLowerCase();
|
||||
client.setUserAuth("hdfs");
|
||||
|
||||
vol = client.createVolume(volumeName, "bilbo", "100TB");
|
||||
VolumeArgs volumeArgs = VolumeArgs.newBuilder()
|
||||
.setOwner("bilbo")
|
||||
.setQuota("100TB")
|
||||
.setAdmin("hdfs")
|
||||
.build();
|
||||
client.createVolume(volumeName, volumeArgs);
|
||||
vol = client.getVolumeDetails(volumeName);
|
||||
String[] acls = {"user:frodo:rw", "user:samwise:rw"};
|
||||
|
||||
String bucketName = OzoneUtils.getRequestID().toLowerCase();
|
||||
bucket = vol.createBucket(bucketName, acls, StorageType.DEFAULT);
|
||||
List<OzoneAcl> aclList =
|
||||
Arrays.stream(acls).map(acl -> OzoneAcl.parseAcl(acl))
|
||||
.collect(Collectors.toList());
|
||||
BucketArgs bucketArgs = BucketArgs.newBuilder()
|
||||
.setAcls(aclList)
|
||||
.build();
|
||||
vol.createBucket(bucketName, bucketArgs);
|
||||
bucket = vol.getBucket(bucketName);
|
||||
|
||||
String fileName = OzoneUtils.getRequestID().toLowerCase();
|
||||
|
||||
file = createRandomDataFile(dir, fileName, 1024);
|
||||
|
||||
bucket.putKey(keyName, file);
|
||||
return new KsmKeyArgs.Builder()
|
||||
.setKeyName(keyName)
|
||||
.setVolumeName(volumeName)
|
||||
.setBucketName(bucketName)
|
||||
.setDataSize(1024)
|
||||
.build();
|
||||
try (
|
||||
OzoneOutputStream ozoneOutputStream = bucket
|
||||
.createKey(keyName, 0, replicationType, replicationFactor);
|
||||
InputStream fileInputStream = new FileInputStream(file)) {
|
||||
IOUtils.copy(fileInputStream, ozoneOutputStream);
|
||||
}
|
||||
return keyName;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutKey() throws Exception {
|
||||
// Test non-delimited keys
|
||||
runTestPutKey(new PutHelper(ozoneRestClient, path));
|
||||
runTestPutKey(new PutHelper(client, path));
|
||||
// Test key delimited by a random delimiter
|
||||
String delimiter = RandomStringUtils.randomAscii(1);
|
||||
runTestPutKey(new PutHelper(ozoneRestClient, path,
|
||||
runTestPutKey(new PutHelper(client, path,
|
||||
getMultiPartKey(delimiter)));
|
||||
}
|
||||
|
||||
static void runTestPutKey(PutHelper helper) throws Exception {
|
||||
final OzoneRestClient client = helper.client;
|
||||
final ClientProtocol client = helper.client;
|
||||
helper.putKey();
|
||||
assertNotNull(helper.getBucket());
|
||||
assertNotNull(helper.getFile());
|
||||
List<OzoneKey> keyList = helper.getBucket().listKeys("100", null, null);
|
||||
List<OzoneKey> keyList = client
|
||||
.listKeys(helper.getVol().getName(), helper.getBucket().getName(), null,
|
||||
null, 10);
|
||||
Assert.assertEquals(1, keyList.size());
|
||||
|
||||
// test list key using a more efficient call
|
||||
String newkeyName = OzoneUtils.getRequestID().toLowerCase();
|
||||
client.putKey(helper.getVol().getVolumeName(),
|
||||
helper.getBucket().getBucketName(), newkeyName, helper.getFile());
|
||||
keyList = helper.getBucket().listKeys("100", null, null);
|
||||
OzoneOutputStream ozoneOutputStream = client
|
||||
.createKey(helper.getVol().getName(), helper.getBucket().getName(),
|
||||
newkeyName, 0, replicationType, replicationFactor);
|
||||
ozoneOutputStream.close();
|
||||
keyList = client
|
||||
.listKeys(helper.getVol().getName(), helper.getBucket().getName(), null,
|
||||
null, 10);
|
||||
Assert.assertEquals(2, keyList.size());
|
||||
|
||||
// test new put key with invalid volume/bucket name
|
||||
try {
|
||||
client.putKey("invalid-volume",
|
||||
helper.getBucket().getBucketName(), newkeyName, helper.getFile());
|
||||
ozoneOutputStream = client
|
||||
.createKey("invalid-volume", helper.getBucket().getName(), newkeyName,
|
||||
0, replicationType, replicationFactor);
|
||||
ozoneOutputStream.close();
|
||||
fail("Put key should have thrown"
|
||||
+ " when using invalid volume name.");
|
||||
} catch (OzoneException e) {
|
||||
} catch (IOException e) {
|
||||
GenericTestUtils.assertExceptionContains(
|
||||
Status.VOLUME_NOT_FOUND.toString(), e);
|
||||
}
|
||||
|
||||
try {
|
||||
client.putKey(helper.getVol().getVolumeName(), "invalid-bucket",
|
||||
newkeyName, helper.getFile());
|
||||
ozoneOutputStream = client
|
||||
.createKey(helper.getVol().getName(), "invalid-bucket", newkeyName, 0,
|
||||
replicationType, replicationFactor);
|
||||
ozoneOutputStream.close();
|
||||
fail("Put key should have thrown "
|
||||
+ "when using invalid bucket name.");
|
||||
} catch (OzoneException e) {
|
||||
} catch (IOException e) {
|
||||
GenericTestUtils.assertExceptionContains(
|
||||
Status.BUCKET_NOT_FOUND.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void restartDatanode(
|
||||
MiniOzoneCluster cluster, int datanodeIdx, OzoneRestClient client)
|
||||
private static void restartDatanode(MiniOzoneCluster cluster, int datanodeIdx)
|
||||
throws OzoneException, URISyntaxException {
|
||||
cluster.restartHddsDatanode(datanodeIdx);
|
||||
// refresh the datanode endpoint uri after datanode restart
|
||||
final int port = ozoneCluster.getHddsDatanodes().get(0)
|
||||
.getDatanodeDetails().getOzoneRestPort();
|
||||
client.setEndPoint(String.format("http://localhost:%d", port));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutAndGetKeyWithDnRestart() throws Exception {
|
||||
runTestPutAndGetKeyWithDnRestart(
|
||||
new PutHelper(ozoneRestClient, path), ozoneCluster);
|
||||
new PutHelper(client, path), ozoneCluster);
|
||||
String delimiter = RandomStringUtils.randomAscii(1);
|
||||
runTestPutAndGetKeyWithDnRestart(
|
||||
new PutHelper(ozoneRestClient, path,
|
||||
new PutHelper(client, path,
|
||||
getMultiPartKey(delimiter)), ozoneCluster);
|
||||
}
|
||||
|
||||
static void runTestPutAndGetKeyWithDnRestart(
|
||||
PutHelper helper, MiniOzoneCluster cluster) throws Exception {
|
||||
String keyName = helper.putKey().getKeyName();
|
||||
String keyName = helper.putKey();
|
||||
assertNotNull(helper.getBucket());
|
||||
assertNotNull(helper.getFile());
|
||||
|
||||
// restart the datanode
|
||||
restartDatanode(cluster, 0, helper.client);
|
||||
restartDatanode(cluster, 0);
|
||||
// TODO: Try removing sleep and adding a join for the MiniOzoneCluster start
|
||||
// The ozoneContainer is not started and its metrics are not initialized
|
||||
// which leads to NullPointerException in Dispatcher.
|
||||
Thread.sleep(1000);
|
||||
ozoneCluster.waitForClusterToBeReady();
|
||||
// verify getKey after the datanode restart
|
||||
String newFileName = helper.dir + "/"
|
||||
+ OzoneUtils.getRequestID().toLowerCase();
|
||||
Path newPath = Paths.get(newFileName);
|
||||
|
||||
helper.getBucket().getKey(keyName, newPath);
|
||||
try (
|
||||
FileOutputStream newOutputStream = new FileOutputStream(
|
||||
newPath.toString());
|
||||
OzoneInputStream ozoneInputStream = helper.client
|
||||
.getKey(helper.getVol().getName(), helper.getBucket().getName(),
|
||||
keyName)) {
|
||||
IOUtils.copy(ozoneInputStream, newOutputStream);
|
||||
}
|
||||
|
||||
try (
|
||||
FileInputStream original = new FileInputStream(helper.getFile());
|
||||
@ -321,16 +365,16 @@ static void runTestPutAndGetKeyWithDnRestart(
|
||||
|
||||
@Test
|
||||
public void testPutAndGetKey() throws Exception {
|
||||
runTestPutAndGetKey(new PutHelper(ozoneRestClient, path));
|
||||
runTestPutAndGetKey(new PutHelper(client, path));
|
||||
String delimiter = RandomStringUtils.randomAscii(1);
|
||||
runTestPutAndGetKey(new PutHelper(ozoneRestClient, path,
|
||||
runTestPutAndGetKey(new PutHelper(client, path,
|
||||
getMultiPartKey(delimiter)));
|
||||
}
|
||||
|
||||
static void runTestPutAndGetKey(PutHelper helper) throws Exception {
|
||||
final OzoneRestClient client = helper.client;
|
||||
final ClientProtocol client = helper.client;
|
||||
|
||||
String keyName = helper.putKey().getKeyName();
|
||||
String keyName = helper.putKey();
|
||||
assertNotNull(helper.getBucket());
|
||||
assertNotNull(helper.getFile());
|
||||
|
||||
@ -342,10 +386,22 @@ static void runTestPutAndGetKey(PutHelper helper) throws Exception {
|
||||
Path newPath1 = Paths.get(newFileName1);
|
||||
Path newPath2 = Paths.get(newFileName2);
|
||||
|
||||
helper.getBucket().getKey(keyName, newPath1);
|
||||
try (
|
||||
FileOutputStream newOutputStream = new FileOutputStream(
|
||||
newPath1.toString());
|
||||
OzoneInputStream ozoneInputStream = helper.getBucket()
|
||||
.readKey(keyName)) {
|
||||
IOUtils.copy(ozoneInputStream, newOutputStream);
|
||||
}
|
||||
|
||||
// test get key using a more efficient call
|
||||
client.getKey(helper.getVol().getVolumeName(),
|
||||
helper.getBucket().getBucketName(), keyName, newPath2);
|
||||
try (
|
||||
FileOutputStream newOutputStream = new FileOutputStream(
|
||||
newPath2.toString());
|
||||
OzoneInputStream ozoneInputStream = helper.getBucket()
|
||||
.readKey(keyName)) {
|
||||
IOUtils.copy(ozoneInputStream, newOutputStream);
|
||||
}
|
||||
|
||||
try (FileInputStream original = new FileInputStream(helper.getFile());
|
||||
FileInputStream downloaded1 = new FileInputStream(newPath1.toFile());
|
||||
@ -363,19 +419,17 @@ static void runTestPutAndGetKey(PutHelper helper) throws Exception {
|
||||
|
||||
// test new get key with invalid volume/bucket name
|
||||
try {
|
||||
client.getKey("invalid-volume", helper.getBucket().getBucketName(),
|
||||
keyName, newPath1);
|
||||
client.getKey("invalid-volume", helper.getBucket().getName(), keyName);
|
||||
fail("Get key should have thrown " + "when using invalid volume name.");
|
||||
} catch (OzoneException e) {
|
||||
} catch (IOException e) {
|
||||
GenericTestUtils
|
||||
.assertExceptionContains(Status.KEY_NOT_FOUND.toString(), e);
|
||||
}
|
||||
|
||||
try {
|
||||
client.getKey(helper.getVol().getVolumeName(), "invalid-bucket",
|
||||
keyName, newPath1);
|
||||
client.getKey(helper.getVol().getName(), "invalid-bucket", keyName);
|
||||
fail("Get key should have thrown " + "when using invalid bucket name.");
|
||||
} catch (OzoneException e) {
|
||||
} catch (IOException e) {
|
||||
GenericTestUtils.assertExceptionContains(
|
||||
Status.KEY_NOT_FOUND.toString(), e);
|
||||
}
|
||||
@ -384,14 +438,14 @@ static void runTestPutAndGetKey(PutHelper helper) throws Exception {
|
||||
|
||||
@Test
|
||||
public void testPutAndDeleteKey() throws Exception {
|
||||
runTestPutAndDeleteKey(new PutHelper(ozoneRestClient, path));
|
||||
runTestPutAndDeleteKey(new PutHelper(client, path));
|
||||
String delimiter = RandomStringUtils.randomAscii(1);
|
||||
runTestPutAndDeleteKey(new PutHelper(ozoneRestClient, path,
|
||||
runTestPutAndDeleteKey(new PutHelper(client, path,
|
||||
getMultiPartKey(delimiter)));
|
||||
}
|
||||
|
||||
static void runTestPutAndDeleteKey(PutHelper helper) throws Exception {
|
||||
String keyName = helper.putKey().getKeyName();
|
||||
String keyName = helper.putKey();
|
||||
assertNotNull(helper.getBucket());
|
||||
assertNotNull(helper.getFile());
|
||||
helper.getBucket().deleteKey(keyName);
|
||||
@ -399,7 +453,7 @@ static void runTestPutAndDeleteKey(PutHelper helper) throws Exception {
|
||||
try {
|
||||
helper.getBucket().getKey(keyName);
|
||||
fail("Get Key on a deleted key should have thrown");
|
||||
} catch (OzoneException ex) {
|
||||
} catch (IOException ex) {
|
||||
GenericTestUtils.assertExceptionContains(
|
||||
Status.KEY_NOT_FOUND.toString(), ex);
|
||||
}
|
||||
@ -407,14 +461,14 @@ static void runTestPutAndDeleteKey(PutHelper helper) throws Exception {
|
||||
|
||||
@Test
|
||||
public void testPutAndListKey() throws Exception {
|
||||
runTestPutAndListKey(new PutHelper(ozoneRestClient, path));
|
||||
runTestPutAndListKey(new PutHelper(client, path));
|
||||
String delimiter = RandomStringUtils.randomAscii(1);
|
||||
runTestPutAndListKey(new PutHelper(ozoneRestClient, path,
|
||||
runTestPutAndListKey(new PutHelper(client, path,
|
||||
getMultiPartKey(delimiter)));
|
||||
}
|
||||
|
||||
static void runTestPutAndListKey(PutHelper helper) throws Exception {
|
||||
final OzoneRestClient client = helper.client;
|
||||
ClientProtocol client = helper.client;
|
||||
helper.putKey();
|
||||
assertNotNull(helper.getBucket());
|
||||
assertNotNull(helper.getFile());
|
||||
@ -422,13 +476,20 @@ static void runTestPutAndListKey(PutHelper helper) throws Exception {
|
||||
// add keys [list-key0, list-key1, ..., list-key9]
|
||||
for (int x = 0; x < 10; x++) {
|
||||
String newkeyName = "list-key" + x;
|
||||
helper.getBucket().putKey(newkeyName, helper.getFile());
|
||||
try (
|
||||
OzoneOutputStream ozoneOutputStream = helper.getBucket()
|
||||
.createKey(newkeyName, 0, replicationType, replicationFactor);
|
||||
InputStream fileInputStream = new FileInputStream(helper.getFile())) {
|
||||
IOUtils.copy(fileInputStream, ozoneOutputStream);
|
||||
}
|
||||
}
|
||||
|
||||
List<OzoneKey> keyList1 = helper.getBucket().listKeys("100", null, null);
|
||||
List<OzoneKey> keyList1 =
|
||||
IteratorUtils.toList(helper.getBucket().listKeys(null, null));
|
||||
// test list key using a more efficient call
|
||||
List<OzoneKey> keyList2 = client.listKeys(helper.getVol().getVolumeName(),
|
||||
helper.getBucket().getBucketName(), "100", null, null);
|
||||
List<OzoneKey> keyList2 = client
|
||||
.listKeys(helper.getVol().getName(), helper.getBucket().getName(), null,
|
||||
null, 100);
|
||||
|
||||
Assert.assertEquals(11, keyList1.size());
|
||||
Assert.assertEquals(11, keyList2.size());
|
||||
@ -436,57 +497,56 @@ static void runTestPutAndListKey(PutHelper helper) throws Exception {
|
||||
// second unit since the date string reparsed to millisecond will
|
||||
// lose precision.
|
||||
for (OzoneKey key : keyList1) {
|
||||
assertTrue((OzoneUtils.formatDate(key.getObjectInfo().getCreatedOn())
|
||||
/ 1000) >= (currentTime / 1000));
|
||||
assertTrue((OzoneUtils.formatDate(key.getObjectInfo().getModifiedOn())
|
||||
/ 1000) >= (currentTime / 1000));
|
||||
assertTrue((key.getCreationTime() / 1000) >= (currentTime / 1000));
|
||||
assertTrue((key.getModificationTime() / 1000) >= (currentTime / 1000));
|
||||
}
|
||||
|
||||
for (OzoneKey key : keyList2) {
|
||||
assertTrue((OzoneUtils.formatDate(key.getObjectInfo().getCreatedOn())
|
||||
/ 1000) >= (currentTime / 1000));
|
||||
assertTrue((OzoneUtils.formatDate(key.getObjectInfo().getModifiedOn())
|
||||
/ 1000) >= (currentTime / 1000));
|
||||
assertTrue((key.getCreationTime() / 1000) >= (currentTime / 1000));
|
||||
assertTrue((key.getModificationTime() / 1000) >= (currentTime / 1000));
|
||||
}
|
||||
|
||||
// test maxLength parameter of list keys
|
||||
keyList1 = helper.getBucket().listKeys("1", null, null);
|
||||
keyList2 = client.listKeys(helper.getVol().getVolumeName(),
|
||||
helper.getBucket().getBucketName(), "1", null, null);
|
||||
Assert.assertEquals(1, keyList1.size());
|
||||
keyList2 = client
|
||||
.listKeys(helper.getVol().getName(), helper.getBucket().getName(), null,
|
||||
null, 1);
|
||||
Assert.assertEquals(1, keyList2.size());
|
||||
|
||||
// test startKey parameter of list keys
|
||||
keyList1 = helper.getBucket().listKeys("100", "list-key4", "list-key");
|
||||
keyList2 = client.listKeys(helper.getVol().getVolumeName(),
|
||||
helper.getBucket().getBucketName(), "100", "list-key4", "list-key");
|
||||
keyList1 = IteratorUtils
|
||||
.toList(helper.getBucket().listKeys("list-key", "list-key4"));
|
||||
keyList2 = client
|
||||
.listKeys(helper.getVol().getName(), helper.getBucket().getName(),
|
||||
"list-key", "list-key4", 100);
|
||||
Assert.assertEquals(5, keyList1.size());
|
||||
Assert.assertEquals(5, keyList2.size());
|
||||
|
||||
// test prefix parameter of list keys
|
||||
keyList1 = helper.getBucket().listKeys("100", null, "list-key2");
|
||||
keyList2 = client.listKeys(helper.getVol().getVolumeName(),
|
||||
helper.getBucket().getBucketName(), "100", null, "list-key2");
|
||||
Assert.assertTrue(keyList1.size() == 1
|
||||
&& keyList1.get(0).getObjectInfo().getKeyName().equals("list-key2"));
|
||||
Assert.assertTrue(keyList2.size() == 1
|
||||
&& keyList2.get(0).getObjectInfo().getKeyName().equals("list-key2"));
|
||||
keyList1 =
|
||||
IteratorUtils.toList(helper.getBucket().listKeys("list-key2", null));
|
||||
keyList2 = client
|
||||
.listKeys(helper.getVol().getName(), helper.getBucket().getName(),
|
||||
"list-key2", null, 100);
|
||||
Assert.assertTrue(
|
||||
keyList1.size() == 1 && keyList1.get(0).getName().equals("list-key2"));
|
||||
Assert.assertTrue(
|
||||
keyList2.size() == 1 && keyList2.get(0).getName().equals("list-key2"));
|
||||
|
||||
// test new list keys with invalid volume/bucket name
|
||||
try {
|
||||
client.listKeys("invalid-volume", helper.getBucket().getBucketName(),
|
||||
"100", null, null);
|
||||
client.listKeys("invalid-volume", helper.getBucket().getName(),
|
||||
null, null, 100);
|
||||
fail("List keys should have thrown when using invalid volume name.");
|
||||
} catch (OzoneException e) {
|
||||
} catch (IOException e) {
|
||||
GenericTestUtils.assertExceptionContains(
|
||||
Status.BUCKET_NOT_FOUND.toString(), e);
|
||||
}
|
||||
|
||||
try {
|
||||
client.listKeys(helper.getVol().getVolumeName(), "invalid-bucket", "100",
|
||||
null, null);
|
||||
client.listKeys(helper.getVol().getName(), "invalid-bucket", null,
|
||||
null, 100);
|
||||
fail("List keys should have thrown when using invalid bucket name.");
|
||||
} catch (OzoneException e) {
|
||||
} catch (IOException e) {
|
||||
GenericTestUtils.assertExceptionContains(
|
||||
Status.BUCKET_NOT_FOUND.toString(), e);
|
||||
}
|
||||
@ -494,29 +554,27 @@ static void runTestPutAndListKey(PutHelper helper) throws Exception {
|
||||
|
||||
@Test
|
||||
public void testGetKeyInfo() throws Exception {
|
||||
runTestGetKeyInfo(new PutHelper(ozoneRestClient, path));
|
||||
runTestGetKeyInfo(new PutHelper(client, path));
|
||||
String delimiter = RandomStringUtils.randomAscii(1);
|
||||
runTestGetKeyInfo(new PutHelper(ozoneRestClient, path,
|
||||
runTestGetKeyInfo(new PutHelper(client, path,
|
||||
getMultiPartKey(delimiter)));
|
||||
}
|
||||
|
||||
static void runTestGetKeyInfo(PutHelper helper) throws Exception {
|
||||
String keyName = helper.putKey().getKeyName();
|
||||
String keyName = helper.putKey();
|
||||
assertNotNull(helper.getBucket());
|
||||
assertNotNull(helper.getFile());
|
||||
|
||||
OzoneKey keyInfo = helper.getBucket().getKeyInfo(keyName);
|
||||
assertNotNull(keyInfo.getObjectInfo());
|
||||
assertEquals(keyName, keyInfo.getObjectInfo().getKeyName());
|
||||
OzoneKey keyInfo = helper.getBucket().getKey(keyName);
|
||||
assertNotNull(keyInfo);
|
||||
assertEquals(keyName, keyInfo.getName());
|
||||
|
||||
// Compare the time in second unit since the date string reparsed to
|
||||
// millisecond will lose precision.
|
||||
Assert
|
||||
.assertTrue((keyInfo.getCreationTime() / 1000) >= (currentTime / 1000));
|
||||
Assert.assertTrue(
|
||||
(OzoneUtils.formatDate(keyInfo.getObjectInfo().getCreatedOn())
|
||||
/ 1000) >= (currentTime / 1000));
|
||||
Assert.assertTrue(
|
||||
(OzoneUtils.formatDate(keyInfo.getObjectInfo().getModifiedOn())
|
||||
/ 1000) >= (currentTime / 1000));
|
||||
(keyInfo.getModificationTime() / 1000) >= (currentTime / 1000));
|
||||
}
|
||||
|
||||
// Volume, bucket, keys info that helps for test create/delete keys.
|
||||
@ -593,12 +651,12 @@ public void testDeleteKey() throws Exception {
|
||||
int numOfExistedKeys = countKsmKeys(ksm);
|
||||
|
||||
// Keep tracking bucket keys info while creating them
|
||||
PutHelper helper = new PutHelper(ozoneRestClient, path);
|
||||
PutHelper helper = new PutHelper(client, path);
|
||||
BucketKeys bucketKeys = new BucketKeys();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
KsmKeyArgs keyArgs = helper.putKey();
|
||||
bucketKeys.addKey(keyArgs.getVolumeName(), keyArgs.getBucketName(),
|
||||
keyArgs.getKeyName());
|
||||
String keyName = helper.putKey();
|
||||
bucketKeys.addKey(helper.getVol().getName(), helper.getBucket().getName(),
|
||||
keyName);
|
||||
}
|
||||
|
||||
// There should be 20 keys in the buckets we just created.
|
||||
|
@ -21,6 +21,7 @@
|
||||
import org.apache.hadoop.ozone.MiniOzoneCluster;
|
||||
import org.apache.hadoop.ozone.OzoneConfigKeys;
|
||||
import org.apache.hadoop.ozone.RatisTestHelper;
|
||||
import org.apache.hadoop.ozone.client.protocol.ClientProtocol;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
@ -52,7 +53,7 @@ public class TestKeysRatis {
|
||||
private static RatisTestHelper.RatisTestSuite suite;
|
||||
private static MiniOzoneCluster ozoneCluster = null;
|
||||
static private String path;
|
||||
private static OzoneRestClient ozoneRestClient = null;
|
||||
private static ClientProtocol client = null;
|
||||
|
||||
@BeforeClass
|
||||
public static void init() throws Exception {
|
||||
@ -60,7 +61,7 @@ public static void init() throws Exception {
|
||||
path = suite.getConf().get(OzoneConfigKeys.OZONE_LOCALSTORAGE_ROOT);
|
||||
ozoneCluster = suite.getCluster();
|
||||
ozoneCluster.waitForClusterToBeReady();
|
||||
ozoneRestClient = suite.newOzoneRestClient();
|
||||
client = suite.newOzoneClient();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,9 +77,9 @@ public static void shutdown() {
|
||||
|
||||
@Test
|
||||
public void testPutKey() throws Exception {
|
||||
runTestPutKey(new PutHelper(ozoneRestClient, path));
|
||||
runTestPutKey(new PutHelper(client, path));
|
||||
String delimiter = RandomStringUtils.randomAlphanumeric(1);
|
||||
runTestPutKey(new PutHelper(ozoneRestClient, path,
|
||||
runTestPutKey(new PutHelper(client, path,
|
||||
getMultiPartKey(delimiter)));
|
||||
}
|
||||
|
||||
@ -86,42 +87,42 @@ public void testPutKey() throws Exception {
|
||||
@Test
|
||||
public void testPutAndGetKeyWithDnRestart() throws Exception {
|
||||
runTestPutAndGetKeyWithDnRestart(
|
||||
new PutHelper(ozoneRestClient, path), ozoneCluster);
|
||||
new PutHelper(client, path), ozoneCluster);
|
||||
String delimiter = RandomStringUtils.randomAlphanumeric(1);
|
||||
runTestPutAndGetKeyWithDnRestart(
|
||||
new PutHelper(ozoneRestClient, path, getMultiPartKey(delimiter)),
|
||||
new PutHelper(client, path, getMultiPartKey(delimiter)),
|
||||
ozoneCluster);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutAndGetKey() throws Exception {
|
||||
runTestPutAndGetKey(new PutHelper(ozoneRestClient, path));
|
||||
runTestPutAndGetKey(new PutHelper(client, path));
|
||||
String delimiter = RandomStringUtils.randomAlphanumeric(1);
|
||||
runTestPutAndGetKey(new PutHelper(ozoneRestClient, path,
|
||||
runTestPutAndGetKey(new PutHelper(client, path,
|
||||
getMultiPartKey(delimiter)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutAndDeleteKey() throws Exception {
|
||||
runTestPutAndDeleteKey(new PutHelper(ozoneRestClient, path));
|
||||
runTestPutAndDeleteKey(new PutHelper(client, path));
|
||||
String delimiter = RandomStringUtils.randomAlphanumeric(1);
|
||||
runTestPutAndDeleteKey(new PutHelper(ozoneRestClient, path,
|
||||
runTestPutAndDeleteKey(new PutHelper(client, path,
|
||||
getMultiPartKey(delimiter)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutAndListKey() throws Exception {
|
||||
runTestPutAndListKey(new PutHelper(ozoneRestClient, path));
|
||||
runTestPutAndListKey(new PutHelper(client, path));
|
||||
String delimiter = RandomStringUtils.randomAlphanumeric(1);
|
||||
runTestPutAndListKey(new PutHelper(ozoneRestClient, path,
|
||||
runTestPutAndListKey(new PutHelper(client, path,
|
||||
getMultiPartKey(delimiter)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetKeyInfo() throws Exception {
|
||||
runTestGetKeyInfo(new PutHelper(ozoneRestClient, path));
|
||||
runTestGetKeyInfo(new PutHelper(client, path));
|
||||
String delimiter = RandomStringUtils.randomAlphanumeric(1);
|
||||
runTestGetKeyInfo(new PutHelper(ozoneRestClient, path,
|
||||
runTestGetKeyInfo(new PutHelper(client, path,
|
||||
getMultiPartKey(delimiter)));
|
||||
}
|
||||
}
|
||||
|
@ -20,50 +20,42 @@
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang.RandomStringUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.hadoop.hdds.client.OzoneQuota;
|
||||
import org.apache.hadoop.ozone.MiniOzoneCluster;
|
||||
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
|
||||
import org.apache.hadoop.ozone.OzoneConfigKeys;
|
||||
import org.apache.hadoop.ozone.OzoneConsts;
|
||||
import org.apache.hadoop.ozone.client.OzoneClientException;
|
||||
import org.apache.hadoop.ozone.protocol.proto.KeySpaceManagerProtocolProtos.Status;
|
||||
import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
|
||||
import org.apache.hadoop.ozone.client.VolumeArgs;
|
||||
import org.apache.hadoop.ozone.client.protocol.ClientProtocol;
|
||||
import org.apache.hadoop.ozone.client.rpc.RpcClient;
|
||||
import org.apache.hadoop.ozone.client.rest.OzoneException;
|
||||
import org.apache.hadoop.ozone.web.request.OzoneQuota;
|
||||
import org.apache.hadoop.ozone.client.OzoneVolume;
|
||||
import org.apache.hadoop.ozone.web.utils.OzoneUtils;
|
||||
import org.apache.hadoop.test.GenericTestUtils;
|
||||
import org.apache.hadoop.util.Time;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.log4j.Level;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mockito.Mockito;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.Ignore;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.Ignore;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Test Ozone Volumes Lifecycle.
|
||||
*/
|
||||
public class TestVolume {
|
||||
private static MiniOzoneCluster cluster = null;
|
||||
private static OzoneRestClient ozoneRestClient = null;
|
||||
private static ClientProtocol client = null;
|
||||
|
||||
/**
|
||||
* Create a MiniDFSCluster for testing.
|
||||
@ -92,8 +84,7 @@ public static void init() throws Exception {
|
||||
final int port = cluster.getHddsDatanodes().get(0)
|
||||
.getDatanodeDetails().getOzoneRestPort();
|
||||
|
||||
ozoneRestClient = new OzoneRestClient(
|
||||
String.format("http://localhost:%d", port));
|
||||
client = new RpcClient(conf);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,128 +99,122 @@ public static void shutdown() {
|
||||
|
||||
@Test
|
||||
public void testCreateVolume() throws Exception {
|
||||
runTestCreateVolume(ozoneRestClient);
|
||||
runTestCreateVolume(client);
|
||||
}
|
||||
|
||||
static void runTestCreateVolume(OzoneRestClient client)
|
||||
static void runTestCreateVolume(ClientProtocol client)
|
||||
throws OzoneException, IOException, ParseException {
|
||||
String volumeName = OzoneUtils.getRequestID().toLowerCase();
|
||||
client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER);
|
||||
|
||||
long currentTime = Time.now();
|
||||
OzoneRestClient mockClient = Mockito.spy(client);
|
||||
List<CloseableHttpClient> mockedClients = mockHttpClients(mockClient);
|
||||
OzoneVolume vol = mockClient.createVolume(volumeName, "bilbo", "100TB");
|
||||
// Verify http clients are properly closed.
|
||||
verifyHttpConnectionClosed(mockedClients);
|
||||
|
||||
assertEquals(vol.getVolumeName(), volumeName);
|
||||
assertEquals(vol.getCreatedby(), "hdfs");
|
||||
assertEquals(vol.getOwnerName(), "bilbo");
|
||||
assertEquals(vol.getQuota().getUnit(), OzoneQuota.Units.TB);
|
||||
assertEquals(vol.getQuota().getSize(), 100);
|
||||
VolumeArgs volumeArgs = VolumeArgs.newBuilder()
|
||||
.setOwner("bilbo")
|
||||
.setQuota("100TB")
|
||||
.setAdmin("hdfs")
|
||||
.build();
|
||||
client.createVolume(volumeName, volumeArgs);
|
||||
OzoneVolume vol = client.getVolumeDetails(volumeName);
|
||||
|
||||
assertEquals(vol.getName(), volumeName);
|
||||
assertEquals(vol.getAdmin(), "hdfs");
|
||||
assertEquals(vol.getOwner(), "bilbo");
|
||||
assertEquals(vol.getQuota(), OzoneQuota.parseQuota("100TB").sizeInBytes());
|
||||
|
||||
// verify the key creation time
|
||||
assertTrue((OzoneUtils.formatDate(vol.getCreatedOn())
|
||||
assertTrue((vol.getCreationTime()
|
||||
/ 1000) >= (currentTime / 1000));
|
||||
|
||||
// Test create a volume with invalid volume name,
|
||||
// not use Rule here because the test method is static.
|
||||
try {
|
||||
String invalidVolumeName = "#" + OzoneUtils.getRequestID().toLowerCase();
|
||||
client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER);
|
||||
mockClient.createVolume(invalidVolumeName, "bilbo", "100TB");
|
||||
client.createVolume(invalidVolumeName);
|
||||
/*
|
||||
//TODO: RestClient and RpcClient should use HddsClientUtils to verify name
|
||||
fail("Except the volume creation be failed because the"
|
||||
+ " volume name starts with an invalid char #");
|
||||
+ " volume name starts with an invalid char #");*/
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof OzoneClientException);
|
||||
assertTrue(e.getMessage().contains("Bucket or Volume name"
|
||||
+ " has an unsupported character : #"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDuplicateVolume() throws OzoneException {
|
||||
runTestCreateDuplicateVolume(ozoneRestClient);
|
||||
public void testCreateDuplicateVolume() throws OzoneException, IOException {
|
||||
runTestCreateDuplicateVolume(client);
|
||||
}
|
||||
|
||||
static void runTestCreateDuplicateVolume(OzoneRestClient client)
|
||||
throws OzoneException {
|
||||
static void runTestCreateDuplicateVolume(ClientProtocol client)
|
||||
throws OzoneException, IOException {
|
||||
try {
|
||||
client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER);
|
||||
client.createVolume("testvol", "bilbo", "100TB");
|
||||
client.createVolume("testvol", "bilbo", "100TB");
|
||||
client.createVolume("testvol");
|
||||
client.createVolume("testvol");
|
||||
assertFalse(true);
|
||||
} catch (OzoneException ex) {
|
||||
// Ozone will throw saying volume already exists
|
||||
GenericTestUtils.assertExceptionContains(
|
||||
Status.VOLUME_ALREADY_EXISTS.toString(), ex);
|
||||
} catch (IOException ioe) {
|
||||
Assert.assertTrue(ioe.getMessage()
|
||||
.contains("Volume creation failed, error:VOLUME_ALREADY_EXISTS"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteVolume() throws OzoneException {
|
||||
runTestDeleteVolume(ozoneRestClient);
|
||||
public void testDeleteVolume() throws OzoneException, IOException {
|
||||
runTestDeleteVolume(client);
|
||||
}
|
||||
|
||||
static void runTestDeleteVolume(OzoneRestClient client)
|
||||
throws OzoneException {
|
||||
static void runTestDeleteVolume(ClientProtocol client)
|
||||
throws OzoneException, IOException {
|
||||
String volumeName = OzoneUtils.getRequestID().toLowerCase();
|
||||
client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER);
|
||||
OzoneVolume vol = client.createVolume(volumeName, "bilbo", "100TB");
|
||||
client.deleteVolume(vol.getVolumeName());
|
||||
client.createVolume(volumeName);
|
||||
client.deleteVolume(volumeName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeOwnerOnVolume() throws Exception {
|
||||
runTestChangeOwnerOnVolume(ozoneRestClient);
|
||||
runTestChangeOwnerOnVolume(client);
|
||||
}
|
||||
|
||||
static void runTestChangeOwnerOnVolume(OzoneRestClient client)
|
||||
throws OzoneException, ParseException {
|
||||
static void runTestChangeOwnerOnVolume(ClientProtocol client)
|
||||
throws OzoneException, ParseException, IOException {
|
||||
String volumeName = OzoneUtils.getRequestID().toLowerCase();
|
||||
client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER);
|
||||
OzoneVolume vol = client.createVolume(volumeName, "bilbo", "100TB");
|
||||
client.createVolume(volumeName);
|
||||
client.getVolumeDetails(volumeName);
|
||||
client.setVolumeOwner(volumeName, "frodo");
|
||||
OzoneVolume newVol = client.getVolume(volumeName);
|
||||
assertEquals(newVol.getOwnerName(), "frodo");
|
||||
OzoneVolume newVol = client.getVolumeDetails(volumeName);
|
||||
assertEquals(newVol.getOwner(), "frodo");
|
||||
// verify if the creation time is missing after setting owner operation
|
||||
assertTrue(OzoneUtils.formatDate(newVol.getCreatedOn()) > 0);
|
||||
assertTrue(newVol.getCreationTime() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeQuotaOnVolume() throws Exception {
|
||||
runTestChangeQuotaOnVolume(ozoneRestClient);
|
||||
runTestChangeQuotaOnVolume(client);
|
||||
}
|
||||
|
||||
static void runTestChangeQuotaOnVolume(OzoneRestClient client)
|
||||
static void runTestChangeQuotaOnVolume(ClientProtocol client)
|
||||
throws OzoneException, IOException, ParseException {
|
||||
String volumeName = OzoneUtils.getRequestID().toLowerCase();
|
||||
client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER);
|
||||
OzoneVolume vol = client.createVolume(volumeName, "bilbo", "100TB");
|
||||
client.setVolumeQuota(volumeName, "1000MB");
|
||||
OzoneVolume newVol = client.getVolume(volumeName);
|
||||
assertEquals(newVol.getQuota().getSize(), 1000);
|
||||
assertEquals(newVol.getQuota().getUnit(), OzoneQuota.Units.MB);
|
||||
client.createVolume(volumeName);
|
||||
client.setVolumeQuota(volumeName, OzoneQuota.parseQuota("1000MB"));
|
||||
OzoneVolume newVol = client.getVolumeDetails(volumeName);
|
||||
assertEquals(newVol.getQuota(), OzoneQuota.parseQuota("1000MB").sizeInBytes());
|
||||
// verify if the creation time is missing after setting quota operation
|
||||
assertTrue(OzoneUtils.formatDate(newVol.getCreatedOn()) > 0);
|
||||
assertTrue(newVol.getCreationTime() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListVolume() throws OzoneException, IOException {
|
||||
runTestListVolume(ozoneRestClient);
|
||||
runTestListVolume(client);
|
||||
}
|
||||
|
||||
static void runTestListVolume(OzoneRestClient client)
|
||||
static void runTestListVolume(ClientProtocol client)
|
||||
throws OzoneException, IOException {
|
||||
client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER);
|
||||
for (int x = 0; x < 10; x++) {
|
||||
String volumeName = OzoneUtils.getRequestID().toLowerCase();
|
||||
OzoneVolume vol = client.createVolume(volumeName, "frodo", "100TB");
|
||||
assertNotNull(vol);
|
||||
client.createVolume(volumeName);
|
||||
}
|
||||
|
||||
List<OzoneVolume> ovols = client.listVolumes("frodo");
|
||||
List<OzoneVolume> ovols = client.listVolumes(null, null, 100);
|
||||
assertTrue(ovols.size() >= 10);
|
||||
}
|
||||
|
||||
@ -237,27 +222,24 @@ static void runTestListVolume(OzoneRestClient client)
|
||||
@Ignore("Takes 3m to run, disable for now.")
|
||||
@Test
|
||||
public void testListVolumePagination() throws OzoneException, IOException {
|
||||
runTestListVolumePagination(ozoneRestClient);
|
||||
runTestListVolumePagination(client);
|
||||
}
|
||||
|
||||
static void runTestListVolumePagination(OzoneRestClient client)
|
||||
static void runTestListVolumePagination(ClientProtocol client)
|
||||
throws OzoneException, IOException {
|
||||
final int volCount = 2000;
|
||||
final int step = 100;
|
||||
client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER);
|
||||
for (int x = 0; x < volCount; x++) {
|
||||
String volumeName = OzoneUtils.getRequestID().toLowerCase();
|
||||
OzoneVolume vol = client.createVolume(volumeName, "frodo", "100TB");
|
||||
assertNotNull(vol);
|
||||
client.createVolume(volumeName);
|
||||
}
|
||||
OzoneVolume prevKey = null;
|
||||
String prevKey = null;
|
||||
int count = 0;
|
||||
int pagecount = 0;
|
||||
while (count < volCount) {
|
||||
List<OzoneVolume> ovols = client.listVolumes("frodo", null, step,
|
||||
prevKey);
|
||||
List<OzoneVolume> ovols = client.listVolumes(null, prevKey, step);
|
||||
count += ovols.size();
|
||||
prevKey = ovols.get(ovols.size() - 1);
|
||||
prevKey = ovols.get(ovols.size() - 1).getName();
|
||||
pagecount++;
|
||||
}
|
||||
assertEquals(volCount / step, pagecount);
|
||||
@ -267,30 +249,35 @@ static void runTestListVolumePagination(OzoneRestClient client)
|
||||
@Ignore
|
||||
@Test
|
||||
public void testListAllVolumes() throws OzoneException, IOException {
|
||||
runTestListAllVolumes(ozoneRestClient);
|
||||
runTestListAllVolumes(client);
|
||||
}
|
||||
|
||||
static void runTestListAllVolumes(OzoneRestClient client)
|
||||
static void runTestListAllVolumes(ClientProtocol client)
|
||||
throws OzoneException, IOException {
|
||||
final int volCount = 200;
|
||||
final int step = 10;
|
||||
client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER);
|
||||
for (int x = 0; x < volCount; x++) {
|
||||
String userName =
|
||||
"frodo" + RandomStringUtils.randomAlphabetic(5).toLowerCase();
|
||||
String volumeName =
|
||||
"vol" + RandomStringUtils.randomAlphabetic(5).toLowerCase();
|
||||
OzoneVolume vol = client.createVolume(volumeName, userName, "100TB");
|
||||
VolumeArgs volumeArgs = VolumeArgs.newBuilder()
|
||||
.setOwner(userName)
|
||||
.setQuota("100TB")
|
||||
.setAdmin("hdfs")
|
||||
.build();
|
||||
client.createVolume(volumeName, volumeArgs);
|
||||
OzoneVolume vol = client.getVolumeDetails(volumeName);
|
||||
assertNotNull(vol);
|
||||
}
|
||||
OzoneVolume prevKey = null;
|
||||
String prevKey = null;
|
||||
int count = 0;
|
||||
int pagecount = 0;
|
||||
while (count < volCount) {
|
||||
List<OzoneVolume> ovols = client.listAllVolumes(null, step, prevKey);
|
||||
List<OzoneVolume> ovols = client.listVolumes(null, prevKey, step);
|
||||
count += ovols.size();
|
||||
if (ovols.size() > 0) {
|
||||
prevKey = ovols.get(ovols.size() - 1);
|
||||
prevKey = ovols.get(ovols.size() - 1).getName();
|
||||
}
|
||||
pagecount++;
|
||||
}
|
||||
@ -301,17 +288,16 @@ static void runTestListAllVolumes(OzoneRestClient client)
|
||||
|
||||
@Test
|
||||
public void testListVolumes() throws Exception {
|
||||
runTestListVolumes(ozoneRestClient);
|
||||
runTestListVolumes(client);
|
||||
}
|
||||
|
||||
static void runTestListVolumes(OzoneRestClient client)
|
||||
static void runTestListVolumes(ClientProtocol client)
|
||||
throws OzoneException, IOException, ParseException {
|
||||
final int volCount = 20;
|
||||
final String user1 = "test-user-a";
|
||||
final String user2 = "test-user-b";
|
||||
|
||||
long currentTime = Time.now();
|
||||
client.setUserAuth(OzoneConsts.OZONE_SIMPLE_HDFS_USER);
|
||||
// Create 20 volumes, 10 for user1 and another 10 for user2.
|
||||
for (int x = 0; x < volCount; x++) {
|
||||
String volumeName;
|
||||
@ -326,109 +312,40 @@ static void runTestListVolumes(OzoneRestClient client)
|
||||
userName = user2;
|
||||
volumeName = "test-vol" + x;
|
||||
}
|
||||
OzoneVolume vol = client.createVolume(volumeName, userName, "100TB");
|
||||
VolumeArgs volumeArgs = VolumeArgs.newBuilder()
|
||||
.setOwner(userName)
|
||||
.setQuota("100TB")
|
||||
.setAdmin("hdfs")
|
||||
.build();
|
||||
client.createVolume(volumeName, volumeArgs);
|
||||
OzoneVolume vol = client.getVolumeDetails(volumeName);
|
||||
assertNotNull(vol);
|
||||
}
|
||||
|
||||
// list all the volumes belong to user1
|
||||
List<OzoneVolume> volumeList = client.listVolumes(user1,
|
||||
null, 100, StringUtils.EMPTY);
|
||||
List<OzoneVolume> volumeList = client.listVolumes(user1, null, null, 100);
|
||||
assertEquals(10, volumeList.size());
|
||||
// verify the owner name and creation time of volume
|
||||
for (OzoneVolume vol : volumeList) {
|
||||
assertTrue(vol.getOwnerName().equals(user1));
|
||||
assertTrue((OzoneUtils.formatDate(vol.getCreatedOn())
|
||||
assertTrue(vol.getOwner().equals(user1));
|
||||
assertTrue((vol.getCreationTime()
|
||||
/ 1000) >= (currentTime / 1000));
|
||||
}
|
||||
|
||||
// test max key parameter of listing volumes
|
||||
volumeList = client.listVolumes(user1, null, 2, StringUtils.EMPTY);
|
||||
volumeList = client.listVolumes(user1, null, null, 2);
|
||||
assertEquals(2, volumeList.size());
|
||||
|
||||
// test prefix parameter of listing volumes
|
||||
volumeList = client.listVolumes(user1, "test-vol10", 100,
|
||||
StringUtils.EMPTY);
|
||||
volumeList = client.listVolumes(user1, "test-vol10", null, 10);
|
||||
assertTrue(volumeList.size() == 1
|
||||
&& volumeList.get(0).getVolumeName().equals("test-vol10"));
|
||||
&& volumeList.get(0).getName().equals("test-vol10"));
|
||||
|
||||
volumeList = client.listVolumes(user1, "test-vol1",
|
||||
100, StringUtils.EMPTY);
|
||||
volumeList = client.listVolumes(user1, "test-vol1", null, 10);
|
||||
assertEquals(5, volumeList.size());
|
||||
|
||||
// test start key parameter of listing volumes
|
||||
volumeList = client.listVolumes(user2, null, 100, "test-vol15");
|
||||
volumeList = client.listVolumes(user2, null, "test-vol15", 10);
|
||||
assertEquals(2, volumeList.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of mocked {@link CloseableHttpClient} used for testing.
|
||||
* The mocked client replaces the actual calls in
|
||||
* {@link OzoneRestClient#newHttpClient()}, it is used to verify
|
||||
* if the invocation of this client is expected. <b>Note</b>, the output
|
||||
* of this method is always used as the input of
|
||||
* {@link TestVolume#verifyHttpConnectionClosed(List)}.
|
||||
*
|
||||
* @param mockedClient mocked ozone client.
|
||||
* @return a list of mocked {@link CloseableHttpClient}.
|
||||
* @throws IOException
|
||||
*/
|
||||
private static List<CloseableHttpClient> mockHttpClients(
|
||||
OzoneRestClient mockedClient)
|
||||
throws IOException {
|
||||
List<CloseableHttpClient> spyHttpClients = new ArrayList<>();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
CloseableHttpClient spyHttpClient = Mockito
|
||||
.spy(HddsClientUtils.newHttpClient());
|
||||
spyHttpClients.add(spyHttpClient);
|
||||
}
|
||||
|
||||
List<CloseableHttpClient> nextReturns =
|
||||
new ArrayList<>(spyHttpClients.subList(1, spyHttpClients.size()));
|
||||
Mockito.when(mockedClient.newHttpClient()).thenReturn(
|
||||
spyHttpClients.get(0),
|
||||
nextReturns.toArray(new CloseableHttpClient[nextReturns.size()]));
|
||||
return spyHttpClients;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used together with
|
||||
* {@link TestVolume#mockHttpClients(OzoneRestClient)} to verify
|
||||
* if the http client is properly closed. It verifies that as long as
|
||||
* a client calls {@link CloseableHttpClient#execute(HttpUriRequest)} to
|
||||
* send request, then it must calls {@link CloseableHttpClient#close()}
|
||||
* close the http connection.
|
||||
*
|
||||
* @param mockedHttpClients
|
||||
*/
|
||||
private static void verifyHttpConnectionClosed(
|
||||
List<CloseableHttpClient> mockedHttpClients) {
|
||||
final AtomicInteger totalCalled = new AtomicInteger();
|
||||
assertTrue(mockedHttpClients.stream().allMatch(closeableHttpClient -> {
|
||||
boolean clientUsed = false;
|
||||
try {
|
||||
verify(closeableHttpClient, times(1)).execute(Mockito.any());
|
||||
totalCalled.incrementAndGet();
|
||||
clientUsed = true;
|
||||
} catch (Throwable e) {
|
||||
// There might be some redundant instances in mockedHttpClients,
|
||||
// it is allowed that a client is not used.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (clientUsed) {
|
||||
try {
|
||||
// If a client is used, ensure the close function is called.
|
||||
verify(closeableHttpClient, times(1)).close();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
System.out.println("Successful connections " + totalCalled.get());
|
||||
assertTrue("The mocked http client should be called at least once.",
|
||||
totalCalled.get() > 0);
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,9 @@
|
||||
import org.apache.hadoop.ozone.OzoneConfigKeys;
|
||||
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
|
||||
|
||||
import org.apache.hadoop.ozone.client.protocol.ClientProtocol;
|
||||
import org.apache.hadoop.ozone.client.rest.OzoneException;
|
||||
import org.apache.hadoop.ozone.client.rpc.RpcClient;
|
||||
import org.apache.hadoop.test.GenericTestUtils;
|
||||
import org.apache.log4j.Level;
|
||||
import org.apache.log4j.Logger;
|
||||
@ -38,7 +40,7 @@
|
||||
public class TestVolumeRatis {
|
||||
@Rule
|
||||
public Timeout testTimeout = new Timeout(300000);
|
||||
private static OzoneRestClient ozoneClient;
|
||||
private static ClientProtocol client;
|
||||
private static MiniOzoneCluster cluster;
|
||||
|
||||
@BeforeClass
|
||||
@ -63,8 +65,7 @@ public static void init() throws Exception {
|
||||
final int port = cluster.getHddsDatanodes().get(0)
|
||||
.getDatanodeDetails().getOzoneRestPort();
|
||||
|
||||
ozoneClient = new OzoneRestClient(
|
||||
String.format("http://localhost:%d", port));
|
||||
client = new RpcClient(conf);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@ -77,53 +78,53 @@ public static void shutdown() {
|
||||
|
||||
@Test
|
||||
public void testCreateVolume() throws Exception {
|
||||
TestVolume.runTestCreateVolume(ozoneClient);
|
||||
TestVolume.runTestCreateVolume(client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDuplicateVolume() throws OzoneException {
|
||||
TestVolume.runTestCreateDuplicateVolume(ozoneClient);
|
||||
public void testCreateDuplicateVolume() throws OzoneException, IOException {
|
||||
TestVolume.runTestCreateDuplicateVolume(client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteVolume() throws OzoneException {
|
||||
TestVolume.runTestDeleteVolume(ozoneClient);
|
||||
public void testDeleteVolume() throws OzoneException, IOException {
|
||||
TestVolume.runTestDeleteVolume(client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeOwnerOnVolume() throws Exception {
|
||||
TestVolume.runTestChangeOwnerOnVolume(ozoneClient);
|
||||
TestVolume.runTestChangeOwnerOnVolume(client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeQuotaOnVolume() throws Exception {
|
||||
TestVolume.runTestChangeQuotaOnVolume(ozoneClient);
|
||||
TestVolume.runTestChangeQuotaOnVolume(client);
|
||||
}
|
||||
|
||||
// TODO: remove @Ignore below once the problem has been resolved.
|
||||
@Ignore("listVolumes not implemented in DistributedStorageHandler")
|
||||
@Test
|
||||
public void testListVolume() throws OzoneException, IOException {
|
||||
TestVolume.runTestListVolume(ozoneClient);
|
||||
TestVolume.runTestListVolume(client);
|
||||
}
|
||||
|
||||
// TODO: remove @Ignore below once the problem has been resolved.
|
||||
@Ignore("See TestVolume.testListVolumePagination()")
|
||||
@Test
|
||||
public void testListVolumePagination() throws OzoneException, IOException {
|
||||
TestVolume.runTestListVolumePagination(ozoneClient);
|
||||
TestVolume.runTestListVolumePagination(client);
|
||||
}
|
||||
|
||||
// TODO: remove @Ignore below once the problem has been resolved.
|
||||
@Ignore("See TestVolume.testListAllVolumes()")
|
||||
@Test
|
||||
public void testListAllVolumes() throws Exception {
|
||||
TestVolume.runTestListAllVolumes(ozoneClient);
|
||||
TestVolume.runTestListAllVolumes(client);
|
||||
}
|
||||
|
||||
@Ignore("Disabling Ratis tests for pipeline work.")
|
||||
@Test
|
||||
public void testListVolumes() throws Exception {
|
||||
TestVolume.runTestListVolumes(ozoneClient);
|
||||
TestVolume.runTestListVolumes(client);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user