blob: 360f4f436aeaf0b2209b958f2ef3ae14226f299f [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* 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.s3.endpoint;
import javax.inject.Inject;
import java.io.IOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.function.Function;
import org.apache.hadoop.hdds.scm.client.HddsClientUtils;
import org.apache.hadoop.ozone.client.OzoneBucket;
import org.apache.hadoop.ozone.client.OzoneClient;
import org.apache.hadoop.ozone.client.OzoneVolume;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes;
import org.apache.hadoop.ozone.s3.SignatureProcessor;
import org.apache.hadoop.ozone.s3.exception.OS3Exception;
import org.apache.hadoop.ozone.s3.exception.S3ErrorTable;
import com.google.common.annotations.VisibleForTesting;
/**
* Basic helpers for all the REST endpoints.
*/
public class EndpointBase {
@Inject
private OzoneClient client;
@Inject
private SignatureProcessor signatureProcessor;
protected OzoneBucket getBucket(OzoneVolume volume, String bucketName)
throws OS3Exception, IOException {
OzoneBucket bucket;
try {
bucket = volume.getBucket(bucketName);
} catch (OMException ex) {
if (ex.getResult() == ResultCodes.KEY_NOT_FOUND) {
throw S3ErrorTable.newError(S3ErrorTable.NO_SUCH_BUCKET, bucketName);
} else {
throw ex;
}
}
return bucket;
}
protected OzoneBucket getBucket(String bucketName)
throws OS3Exception, IOException {
OzoneBucket bucket;
try {
bucket = client.getObjectStore().getS3Bucket(bucketName);
} catch (OMException ex) {
if (ex.getResult() == ResultCodes.BUCKET_NOT_FOUND
|| ex.getResult() == ResultCodes.VOLUME_NOT_FOUND) {
throw S3ErrorTable.newError(S3ErrorTable.NO_SUCH_BUCKET, bucketName);
} else if (ex.getResult() == ResultCodes.PERMISSION_DENIED) {
throw S3ErrorTable.newError(S3ErrorTable.ACCESS_DENIED, bucketName);
} else {
throw ex;
}
}
return bucket;
}
protected OzoneVolume getVolume() throws IOException {
String s3VolumeName = HddsClientUtils.getS3VolumeName(
client.getConfiguration());
return client.getObjectStore().getVolume(s3VolumeName);
}
/**
* Create an S3Bucket, and also it creates mapping needed to access via
* ozone and S3.
* @param bucketName
* @return location of the S3Bucket.
* @throws IOException
*/
protected String createS3Bucket(String bucketName) throws
IOException, OS3Exception {
try {
client.getObjectStore().createS3Bucket(bucketName);
} catch (OMException ex) {
if (ex.getResult() == ResultCodes.PERMISSION_DENIED) {
throw S3ErrorTable.newError(S3ErrorTable.ACCESS_DENIED, bucketName);
} else if (ex.getResult() != ResultCodes.BUCKET_ALREADY_EXISTS) {
// S3 does not return error for bucket already exists, it just
// returns the location.
throw ex;
}
}
return "/" + bucketName;
}
/**
* Deletes an s3 bucket and removes mapping of Ozone volume/bucket.
* @param s3BucketName - S3 Bucket Name.
* @throws IOException in case the bucket cannot be deleted.
*/
public void deleteS3Bucket(String s3BucketName)
throws IOException, OS3Exception {
try {
client.getObjectStore().deleteS3Bucket(s3BucketName);
} catch (OMException ex) {
if (ex.getResult() == ResultCodes.PERMISSION_DENIED) {
throw S3ErrorTable.newError(S3ErrorTable.ACCESS_DENIED,
s3BucketName);
}
throw ex;
}
}
/**
* Returns Iterator to iterate over all buckets for a specific user.
* The result can be restricted using bucket prefix, will return all
* buckets if bucket prefix is null.
*
* @param prefix Bucket prefix to match
* @return {@code Iterator<OzoneBucket>}
*/
public Iterator<? extends OzoneBucket> listS3Buckets(String prefix)
throws IOException, OS3Exception {
return iterateBuckets(volume -> volume.listBuckets(prefix));
}
/**
* Returns Iterator to iterate over all buckets after prevBucket for a
* specific user. If prevBucket is null it returns an iterator to iterate
* over all buckets for this user. The result can be restricted using
* bucket prefix, will return all buckets if bucket prefix is null.
*
* @param prefix Bucket prefix to match
* @param previousBucket Buckets are listed after this bucket
* @return {@code Iterator<OzoneBucket>}
*/
public Iterator<? extends OzoneBucket> listS3Buckets(String prefix,
String previousBucket) throws IOException, OS3Exception {
return iterateBuckets(volume -> volume.listBuckets(prefix, previousBucket));
}
private Iterator<? extends OzoneBucket> iterateBuckets(
Function<OzoneVolume, Iterator<? extends OzoneBucket>> query)
throws IOException, OS3Exception{
try {
return query.apply(getVolume());
} catch (OMException e) {
if (e.getResult() == ResultCodes.VOLUME_NOT_FOUND) {
return Collections.emptyIterator();
} else if (e.getResult() == ResultCodes.PERMISSION_DENIED) {
throw S3ErrorTable.newError(S3ErrorTable.ACCESS_DENIED,
"listBuckets");
} else {
throw e;
}
}
}
public SignatureProcessor getSignatureProcessor() {
return signatureProcessor;
}
@VisibleForTesting
public void setSignatureProcessor(
SignatureProcessor signatureProcessor) {
this.signatureProcessor = signatureProcessor;
}
@VisibleForTesting
public void setClient(OzoneClient ozoneClient) {
this.client = ozoneClient;
}
}