HDDS-45. Removal of old OzoneRestClient. Contributed by Lokesh Jain.
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/774daa8d Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/774daa8d Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/774daa8d Branch: refs/heads/YARN-7402 Commit: 774daa8d532f9eeee1fe8e342a8da2cfa65a8629 Parents: c05b5d4 Author: Mukul Kumar Singh <msi...@apache.org> Authored: Thu May 24 15:53:42 2018 +0530 Committer: Mukul Kumar Singh <msi...@apache.org> Committed: Thu May 24 15:53:42 2018 +0530 ---------------------------------------------------------------------- .../apache/hadoop/hdds/scm/XceiverClient.java | 22 +- .../hadoop/ozone/web/client/OzoneBucket.java | 646 --------------- .../hadoop/ozone/web/client/OzoneKey.java | 44 - .../ozone/web/client/OzoneRestClient.java | 804 ------------------- .../hadoop/ozone/web/client/OzoneVolume.java | 584 -------------- .../hadoop/ozone/web/client/package-info.java | 34 - .../hadoop/ozone/MiniOzoneClusterImpl.java | 3 +- .../apache/hadoop/ozone/RatisTestHelper.java | 14 +- .../ozone/web/TestOzoneRestWithMiniCluster.java | 207 ++--- .../hadoop/ozone/web/client/TestBuckets.java | 193 +++-- .../ozone/web/client/TestBucketsRatis.java | 15 +- .../hadoop/ozone/web/client/TestKeys.java | 286 ++++--- .../hadoop/ozone/web/client/TestKeysRatis.java | 29 +- .../hadoop/ozone/web/client/TestVolume.java | 285 +++---- .../ozone/web/client/TestVolumeRatis.java | 29 +- 15 files changed, 548 insertions(+), 2647 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hadoop/blob/774daa8d/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClient.java ---------------------------------------------------------------------- diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClient.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClient.java index 6d33cd4..42e02f9 100644 --- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClient.java +++ b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClient.java @@ -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 class XceiverClient extends XceiverClientSpi { @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 class XceiverClient extends XceiverClientSpi { 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 class XceiverClient extends XceiverClientSpi { @Override public void close() { + closed = true; if (group != null) { group.shutdownGracefully().awaitUninterruptibly(); } @@ -124,7 +142,7 @@ public class XceiverClient extends XceiverClientSpi { 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 class XceiverClient extends XceiverClientSpi { 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); http://git-wip-us.apache.org/repos/asf/hadoop/blob/774daa8d/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneBucket.java ---------------------------------------------------------------------- diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneBucket.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneBucket.java deleted file mode 100644 index 3183d03..0000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneBucket.java +++ /dev/null @@ -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); - } - } - } -} http://git-wip-us.apache.org/repos/asf/hadoop/blob/774daa8d/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneKey.java ---------------------------------------------------------------------- diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneKey.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneKey.java deleted file mode 100644 index 5a3a0c4..0000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneKey.java +++ /dev/null @@ -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; - } - -} http://git-wip-us.apache.org/repos/asf/hadoop/blob/774daa8d/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneRestClient.java ---------------------------------------------------------------------- diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneRestClient.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneRestClient.java deleted file mode 100644 index 8373f67..0000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneRestClient.java +++ /dev/null @@ -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(); - } -} http://git-wip-us.apache.org/repos/asf/hadoop/blob/774daa8d/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneVolume.java ---------------------------------------------------------------------- diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneVolume.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneVolume.java deleted file mode 100644 index 9d3831c..0000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/OzoneVolume.java +++ /dev/null @@ -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(); - } -} http://git-wip-us.apache.org/repos/asf/hadoop/blob/774daa8d/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/package-info.java ---------------------------------------------------------------------- diff --git a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/package-info.java b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/package-info.java deleted file mode 100644 index 046568b..0000000 --- a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/web/client/package-info.java +++ /dev/null @@ -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. - **/ http://git-wip-us.apache.org/repos/asf/hadoop/blob/774daa8d/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/MiniOzoneClusterImpl.java ---------------------------------------------------------------------- diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/MiniOzoneClusterImpl.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/MiniOzoneClusterImpl.java index 9936815..ad8b016 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/MiniOzoneClusterImpl.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/MiniOzoneClusterImpl.java @@ -37,7 +37,6 @@ import org.apache.hadoop.ozone.ksm.KSMConfigKeys; 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 final class MiniOzoneClusterImpl implements MiniOzoneCluster { } /** - * 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 http://git-wip-us.apache.org/repos/asf/hadoop/blob/774daa8d/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/RatisTestHelper.java ---------------------------------------------------------------------- diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/RatisTestHelper.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/RatisTestHelper.java index 9aefe9a..1a35c50 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/RatisTestHelper.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/RatisTestHelper.java @@ -20,8 +20,9 @@ package org.apache.hadoop.ozone; 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 interface RatisTestHelper { 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 @@ public interface RatisTestHelper { .setNumDatanodes(numDatanodes).build(); return cluster; } - - static OzoneRestClient newOzoneRestClient(int port) - throws OzoneException, URISyntaxException { - return new OzoneRestClient("http://localhost:" + port); - } } --------------------------------------------------------------------- To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org For additional commands, e-mail: common-commits-h...@hadoop.apache.org