/*************************************************************************
* Copyright 2009-2015 Eucalyptus Systems, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
* Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
* CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
* additional information or have any questions.
************************************************************************/
package com.eucalyptus.objectstorage.providers.s3;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.annotation.Nonnull;
import org.apache.log4j.Logger;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.AbortMultipartUploadRequest;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.BucketLoggingConfiguration;
import com.amazonaws.services.s3.model.BucketVersioningConfiguration;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.CanonicalGrantee;
import com.amazonaws.services.s3.model.CompleteMultipartUploadRequest;
import com.amazonaws.services.s3.model.CompleteMultipartUploadResult;
import com.amazonaws.services.s3.model.CopyObjectRequest;
import com.amazonaws.services.s3.model.CopyObjectResult;
import com.amazonaws.services.s3.model.EmailAddressGrantee;
import com.amazonaws.services.s3.model.GetObjectMetadataRequest;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.GroupGrantee;
import com.amazonaws.services.s3.model.InitiateMultipartUploadRequest;
import com.amazonaws.services.s3.model.InitiateMultipartUploadResult;
import com.amazonaws.services.s3.model.ListBucketsRequest;
import com.amazonaws.services.s3.model.ListMultipartUploadsRequest;
import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ListPartsRequest;
import com.amazonaws.services.s3.model.ListVersionsRequest;
import com.amazonaws.services.s3.model.MultipartUpload;
import com.amazonaws.services.s3.model.MultipartUploadListing;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PartETag;
import com.amazonaws.services.s3.model.PartListing;
import com.amazonaws.services.s3.model.PartSummary;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.PutObjectResult;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.amazonaws.services.s3.model.S3VersionSummary;
import com.amazonaws.services.s3.model.SetBucketLoggingConfigurationRequest;
import com.amazonaws.services.s3.model.SetBucketVersioningConfigurationRequest;
import com.amazonaws.services.s3.model.UploadPartRequest;
import com.amazonaws.services.s3.model.UploadPartResult;
import com.amazonaws.services.s3.model.VersionListing;
import com.eucalyptus.auth.principal.User;
import com.eucalyptus.auth.principal.UserPrincipal;
import com.eucalyptus.objectstorage.client.OsgInternalS3Client;
import com.eucalyptus.objectstorage.entities.S3ProviderConfiguration;
import com.eucalyptus.objectstorage.exceptions.S3ExceptionMapper;
import com.eucalyptus.objectstorage.exceptions.s3.InternalErrorException;
import com.eucalyptus.objectstorage.exceptions.s3.NotImplementedException;
import com.eucalyptus.objectstorage.exceptions.s3.S3Exception;
import com.eucalyptus.objectstorage.msgs.AbortMultipartUploadResponseType;
import com.eucalyptus.objectstorage.msgs.AbortMultipartUploadType;
import com.eucalyptus.objectstorage.msgs.CompleteMultipartUploadResponseType;
import com.eucalyptus.objectstorage.msgs.CompleteMultipartUploadType;
import com.eucalyptus.objectstorage.msgs.CopyObjectResponseType;
import com.eucalyptus.objectstorage.msgs.CopyObjectType;
import com.eucalyptus.objectstorage.msgs.CreateBucketResponseType;
import com.eucalyptus.objectstorage.msgs.CreateBucketType;
import com.eucalyptus.objectstorage.msgs.DeleteBucketResponseType;
import com.eucalyptus.objectstorage.msgs.DeleteBucketType;
import com.eucalyptus.objectstorage.msgs.DeleteObjectResponseType;
import com.eucalyptus.objectstorage.msgs.DeleteObjectType;
import com.eucalyptus.objectstorage.msgs.DeleteVersionResponseType;
import com.eucalyptus.objectstorage.msgs.DeleteVersionType;
import com.eucalyptus.objectstorage.msgs.GetBucketAccessControlPolicyResponseType;
import com.eucalyptus.objectstorage.msgs.GetBucketAccessControlPolicyType;
import com.eucalyptus.objectstorage.msgs.GetBucketLocationResponseType;
import com.eucalyptus.objectstorage.msgs.GetBucketLocationType;
import com.eucalyptus.objectstorage.msgs.GetBucketLoggingStatusResponseType;
import com.eucalyptus.objectstorage.msgs.GetBucketLoggingStatusType;
import com.eucalyptus.objectstorage.msgs.GetBucketVersioningStatusResponseType;
import com.eucalyptus.objectstorage.msgs.GetBucketVersioningStatusType;
import com.eucalyptus.objectstorage.msgs.GetObjectAccessControlPolicyResponseType;
import com.eucalyptus.objectstorage.msgs.GetObjectAccessControlPolicyType;
import com.eucalyptus.objectstorage.msgs.GetObjectExtendedResponseType;
import com.eucalyptus.objectstorage.msgs.GetObjectExtendedType;
import com.eucalyptus.objectstorage.msgs.GetObjectResponseType;
import com.eucalyptus.objectstorage.msgs.GetObjectType;
import com.eucalyptus.objectstorage.msgs.HeadBucketResponseType;
import com.eucalyptus.objectstorage.msgs.HeadBucketType;
import com.eucalyptus.objectstorage.msgs.HeadObjectResponseType;
import com.eucalyptus.objectstorage.msgs.HeadObjectType;
import com.eucalyptus.objectstorage.msgs.InitiateMultipartUploadResponseType;
import com.eucalyptus.objectstorage.msgs.InitiateMultipartUploadType;
import com.eucalyptus.objectstorage.msgs.ListAllMyBucketsResponseType;
import com.eucalyptus.objectstorage.msgs.ListAllMyBucketsType;
import com.eucalyptus.objectstorage.msgs.ListBucketResponseType;
import com.eucalyptus.objectstorage.msgs.ListBucketType;
import com.eucalyptus.objectstorage.msgs.ListMultipartUploadsResponseType;
import com.eucalyptus.objectstorage.msgs.ListMultipartUploadsType;
import com.eucalyptus.objectstorage.msgs.ListPartsResponseType;
import com.eucalyptus.objectstorage.msgs.ListPartsType;
import com.eucalyptus.objectstorage.msgs.ListVersionsResponseType;
import com.eucalyptus.objectstorage.msgs.ListVersionsType;
import com.eucalyptus.objectstorage.msgs.ObjectStorageDataResponseType;
import com.eucalyptus.objectstorage.msgs.ObjectStorageRequestType;
import com.eucalyptus.objectstorage.msgs.PostObjectResponseType;
import com.eucalyptus.objectstorage.msgs.PostObjectType;
import com.eucalyptus.objectstorage.msgs.PutObjectResponseType;
import com.eucalyptus.objectstorage.msgs.PutObjectType;
import com.eucalyptus.objectstorage.msgs.SetBucketAccessControlPolicyResponseType;
import com.eucalyptus.objectstorage.msgs.SetBucketAccessControlPolicyType;
import com.eucalyptus.objectstorage.msgs.SetBucketLoggingStatusResponseType;
import com.eucalyptus.objectstorage.msgs.SetBucketLoggingStatusType;
import com.eucalyptus.objectstorage.msgs.SetBucketVersioningStatusResponseType;
import com.eucalyptus.objectstorage.msgs.SetBucketVersioningStatusType;
import com.eucalyptus.objectstorage.msgs.SetObjectAccessControlPolicyResponseType;
import com.eucalyptus.objectstorage.msgs.SetObjectAccessControlPolicyType;
import com.eucalyptus.objectstorage.msgs.UploadPartResponseType;
import com.eucalyptus.objectstorage.msgs.UploadPartType;
import com.eucalyptus.objectstorage.providers.ObjectStorageProviderClient;
import com.eucalyptus.objectstorage.util.AclUtils;
import com.eucalyptus.objectstorage.util.ObjectStorageProperties;
import com.eucalyptus.storage.common.DateFormatter;
import com.eucalyptus.storage.config.ConfigurationCache;
import com.eucalyptus.storage.msgs.s3.AccessControlList;
import com.eucalyptus.storage.msgs.s3.AccessControlPolicy;
import com.eucalyptus.storage.msgs.s3.BucketListEntry;
import com.eucalyptus.storage.msgs.s3.CanonicalUser;
import com.eucalyptus.storage.msgs.s3.CommonPrefixesEntry;
import com.eucalyptus.storage.msgs.s3.DeleteMarkerEntry;
import com.eucalyptus.storage.msgs.s3.Grant;
import com.eucalyptus.storage.msgs.s3.Grantee;
import com.eucalyptus.storage.msgs.s3.Group;
import com.eucalyptus.storage.msgs.s3.Initiator;
import com.eucalyptus.storage.msgs.s3.KeyEntry;
import com.eucalyptus.storage.msgs.s3.ListAllMyBucketsList;
import com.eucalyptus.storage.msgs.s3.ListEntry;
import com.eucalyptus.storage.msgs.s3.LoggingEnabled;
import com.eucalyptus.storage.msgs.s3.MetaDataEntry;
import com.eucalyptus.storage.msgs.s3.Part;
import com.eucalyptus.storage.msgs.s3.VersionEntry;
import com.eucalyptus.util.EucalyptusCloudException;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
/**
* Base class for S3-api based backends. Uses the Amazon Java SDK as the client. Can be extended for additional capabilities.
*
* The S3ProviderClient does IAM evaluation prior to dispatching requests to the backend and will validate all results upon receipt of the response
* from the backend (e.g. for listing buckets).
*
* Current implementation maps all Euca credentials to a single backend s3 credential as configured in {@link S3ProviderConfiguration}. The
* implication is that this provider will not enforce ACLs, policies, or any separation between Euca-users.
*
*/
public class S3ProviderClient implements ObjectStorageProviderClient {
private static final Logger LOG = Logger.getLogger(S3ProviderClient.class);
private volatile URI upstreamEndpoint;
private volatile OsgInternalS3Client backendClient;
/**
* Returns a usable S3 Client configured to send requests to the currently configured endpoint with the currently configured credentials.
*
* @return
*/
protected OsgInternalS3Client getS3Client(User requestUser) throws InternalErrorException {
S3ProviderConfiguration providerConfig = ConfigurationCache.getConfiguration(S3ProviderConfiguration.class);
AWSCredentials credentials;
try {
credentials = mapCredentials(requestUser);
} catch (Exception e) {
LOG.error("Error mapping credentials for user " + (requestUser != null ? requestUser.getUserId() : "null") + " for walrus backend call.", e);
throw new InternalErrorException(
"Cannot construct s3client due to inability to map credentials for user: " + (requestUser != null ? requestUser.getUserId() : "null"), e);
}
if (this.backendClient == null) {
synchronized (this) {
if (this.backendClient == null) {
try {
// Create new one
this.backendClient = new OsgInternalS3Client(credentials, this.getUpstreamEndpoint().toASCIIString(), providerConfig.getS3UseHttps(),
providerConfig.getS3UseBackendDns());
return this.backendClient;
} catch (Exception e) {
LOG.error("exception thrown retrieving internal s3 client", e);
throw new InternalErrorException("Cannot get s3client from pool", e);
}
}
}
}
try {
this.backendClient.update(credentials, this.getUpstreamEndpoint().toASCIIString(), providerConfig.getS3UseHttps(),
providerConfig.getS3UseBackendDns());
return this.backendClient;
} catch (Exception e) {
throw new InternalErrorException(e);
}
}
protected URI getUpstreamEndpoint() throws URISyntaxException {
String raw = ConfigurationCache.getConfiguration(S3ProviderConfiguration.class).getS3Endpoint();
if (upstreamEndpoint == null
|| !(upstreamEndpoint.getHost().equals(getUpstreamEndpointHost(raw)) && upstreamEndpoint.getPort() == getUpstreamEndpointPort(raw))) {
synchronized (this) {
upstreamEndpoint = convertToFullURI(raw);
}
}
return upstreamEndpoint;
}
/**
* Returns valid URI with port, will assign 80 if not specified explicitly and will add a 'http' scheme if none found.
*
* @param raw
* @return
*/
protected URI convertToFullURI(@Nonnull String raw) {
URI tmp;
if (!raw.startsWith("http://") && !raw.startsWith("https://")) {
// Add the scheme
raw = "http://" + raw;
}
tmp = URI.create(raw);
if (tmp.getPort() != -1) {
return tmp; // It's valid
} else {
return URI.create(raw + ":80"); // just add default http port
}
}
protected String getUpstreamEndpointHost(@Nonnull String raw) {
String[] s3EndpointParts = raw.split(":");
if (s3EndpointParts.length > 0) {
return s3EndpointParts[0];
} else {
return null;
}
}
protected int getUpstreamEndpointPort(@Nonnull String raw) {
String[] s3EndpointParts = raw.split(":");
if (s3EndpointParts.length > 1) {
try {
return Integer.parseInt(s3EndpointParts[1]);
} catch (NumberFormatException e) {
return 80;
}
} else {
return 80; // default http port
}
}
protected boolean doUsePathStyle() {
return !ConfigurationCache.getConfiguration(S3ProviderConfiguration.class).getS3UseBackendDns();
}
/**
* Returns the S3 ACL in euca object form. Does not modify the results, so owner information will be preserved.
*
* @param s3Acl
* @return
*/
protected static AccessControlPolicy sdkAclToEucaAcl(com.amazonaws.services.s3.model.AccessControlList s3Acl) {
if (s3Acl == null) {
return null;
}
AccessControlPolicy acp = new AccessControlPolicy();
acp.setOwner(new CanonicalUser(acp.getOwner().getID(), acp.getOwner().getDisplayName()));
if (acp.getAccessControlList() == null) {
acp.setAccessControlList(new AccessControlList());
}
Grantee grantee = null;
for (com.amazonaws.services.s3.model.Grant g : s3Acl.getGrants()) {
grantee = new Grantee();
if (g.getGrantee() instanceof CanonicalGrantee) {
grantee.setCanonicalUser(new CanonicalUser(g.getGrantee().getIdentifier(), ((CanonicalGrantee) g.getGrantee()).getDisplayName()));
} else if (g.getGrantee() instanceof GroupGrantee) {
grantee.setGroup(new Group(g.getGrantee().getIdentifier()));
} else if (g.getGrantee() instanceof EmailAddressGrantee) {
grantee.setEmailAddress(g.getGrantee().getIdentifier());
}
acp.getAccessControlList().getGrants().add(new Grant(grantee, g.getPermission().toString()));
}
return acp;
}
/**
* Maps the request credentials to another set of credentials. This implementation maps all Eucalyptus credentials to a single s3/backend
* credential.
*
* @param requestUser The Eucalyptus user that generated the request
* @return a BasicAWSCredentials object initialized with the credentials to use
* @throws NoSuchElementException
* @throws IllegalArgumentException
*/
protected BasicAWSCredentials mapCredentials(User requestUser) throws Exception {
return new BasicAWSCredentials(ConfigurationCache.getConfiguration(S3ProviderConfiguration.class).getS3AccessKey(),
ConfigurationCache.getConfiguration(S3ProviderConfiguration.class).getS3SecretKey());
}
private static final List<String> copyableHeaders = Collections.unmodifiableList(Lists.newArrayList(
// per REST API PUT Object docs as of 10/13/2014
HttpHeaders.Names.CACHE_CONTROL, "Content-Disposition", // strangely not included
HttpHeaders.Names.CONTENT_ENCODING, HttpHeaders.Names.EXPIRES));
protected ObjectMetadata getS3ObjectMetadata(PutObjectType request) {
ObjectMetadata meta = new ObjectMetadata();
if (request.getMetaData() != null) {
for (MetaDataEntry m : request.getMetaData()) {
meta.addUserMetadata(m.getName(), m.getValue());
}
}
if (!Strings.isNullOrEmpty(request.getContentLength())) {
meta.setContentLength(Long.parseLong(request.getContentLength()));
}
if (!Strings.isNullOrEmpty(request.getContentMD5())) {
meta.setContentMD5(request.getContentMD5());
}
if (!Strings.isNullOrEmpty(request.getContentType())) {
meta.setContentType(request.getContentType());
}
Map<String, String> headersToCopy = request.getCopiedHeaders();
if (headersToCopy != null && headersToCopy.size() > 0) {
for (String header : copyableHeaders) {
// content-length, content-md5 and content-type are copied above
if (headersToCopy.containsKey(header)) {
String v = headersToCopy.get(header);
if (HttpHeaders.Names.CACHE_CONTROL.equals(header)) {
meta.setCacheControl(v);
}
if ("Content-Disposition".equals(header)) {
meta.setContentDisposition(v);
}
if (HttpHeaders.Names.CONTENT_ENCODING.equals(header)) {
meta.setContentEncoding(v);
}
if (HttpHeaders.Names.EXPIRES.equals(header)) {
Date expireDate = DateFormatter.dateFromHeaderFormattedString(v);
if (expireDate != null) {
meta.setHttpExpiresDate(expireDate);
}
}
}
}
}
return meta;
}
@Override
public void initialize() throws EucalyptusCloudException {
LOG.debug("Initializing S3ProviderClient");
// Prime the cache, initializes defaults etc. This is a bit ugly but needs to be provider-specific
ConfigurationCache.getConfiguration(S3ProviderConfiguration.class);
check();
LOG.debug("Initialization completed successfully");
}
@Override
public void check() throws EucalyptusCloudException {
// HEAD to / returns HTTP 405 for S3, RiakCS. 200 for Ceph-RGW. Response value can be configured
checkConnectivityUsingHead(ConfigurationCache.getConfiguration(S3ProviderConfiguration.class).getS3EndpointHeadResponse());
}
private void checkConnectivityUsingHead(Integer expectedResponse) throws EucalyptusCloudException {
LOG.debug("Checking connectivity to S3 endpoint");
if (expectedResponse == null) {
throw new EucalyptusCloudException("S3 provider HEAD op code is not set");
}
try {
int headResponse = excuteHeadRequest(this.getUpstreamEndpoint());
if (headResponse != expectedResponse) {
LOG.warn("Connectivity check to S3 endpoint failed. Expected HEAD op against " + this.getUpstreamEndpoint() + " to return HTTP response "
+ expectedResponse + ", but got " + headResponse);
throw new EucalyptusCloudException(
"Connectivity check to S3 endpoint failed. Expected HEAD op against " + this.getUpstreamEndpoint() + " to return HTTP response "
+ expectedResponse + ", but got " + headResponse + ". Please check configuration and network connection to S3 endpoint");
} else {
LOG.debug("Connectivity check to S3 endpoint completed successfully. HEAD op against " + this.getUpstreamEndpoint()
+ " returned expected HTTP response " + headResponse);
}
} catch (Exception e) {
// it is safe to do this because we won't try to execute an operation until enable returns successfully.
LOG.warn("Connectivity check to S3 endpoint failed", e);
throw new EucalyptusCloudException("Connectivity check to S3 endpoint failed. Please check configuration and network connection to S3 endpoint",
e);
}
}
protected int excuteHeadRequest(URI targetURI) {
LOG.trace("Executing HEAD op on " + targetURI);
HttpURLConnection connection = null;
int code = 500;
try {
connection = (HttpURLConnection) targetURI.toURL().openConnection();
connection.setRequestMethod("HEAD");
connection.setUseCaches(false);
try {
connection.getInputStream();
code = connection.getResponseCode();
} catch (IOException ex) {
code = connection.getResponseCode();
}
LOG.trace("HEAD op response HTTP " + code);
return code;
} catch (Exception ex) {
LOG.warn("Failed to execute HEAD operation on " + targetURI, ex);
return code;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
@Override
public void checkPreconditions() throws EucalyptusCloudException {
LOG.debug("Checking preconditions");
LOG.debug("Check preconditions completed successfully");
}
@Override
public void start() throws EucalyptusCloudException {
LOG.debug("Starting");
LOG.debug("Start completed successfully");
}
@Override
public void stop() throws EucalyptusCloudException {
LOG.debug("Stopping");
// Force a new load of this on startup.
// flushClientPools();
LOG.debug("Stop completed successfully");
}
@Override
public void enable() throws EucalyptusCloudException {
LOG.debug("Enabling");
LOG.debug("Enable completed successfully");
}
@Override
public void disable() throws EucalyptusCloudException {
LOG.debug("Disabling");
LOG.debug("Disable completed successfully");
}
protected CanonicalUser getCanonicalUser(UserPrincipal usr) {
return AclUtils.buildCanonicalUser(usr);
}
/*
* TODO: add multi-account support on backend and then this can be a pass-thru to backend for bucket listing. Multiplexing a single eucalyptus
* account on the backend means we have to track all of the user buckets ourselves (non-Javadoc)
*
* @see com.eucalyptus.objectstorage.ObjectStorageProviderClient#listAllMyBuckets(com.eucalyptus.objectstorage.msgs.ListAllMyBucketsType)
*/
@Override
public ListAllMyBucketsResponseType listAllMyBuckets(ListAllMyBucketsType request) throws S3Exception {
ListAllMyBucketsResponseType reply = request.getReply();
OsgInternalS3Client internalS3Client = null;
User requestUser = null;
try {
requestUser = getRequestUser(request);
// The euca-types
ListAllMyBucketsList myBucketList = new ListAllMyBucketsList();
myBucketList.setBuckets(new ArrayList<BucketListEntry>());
// The s3 client types
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
ListBucketsRequest listRequest = new ListBucketsRequest();
// Map s3 client result to euca response message
List<Bucket> result = s3Client.listBuckets(listRequest);
for (Bucket b : result) {
myBucketList.getBuckets().add(new BucketListEntry(b.getName(), DateFormatter.dateToHeaderFormattedString(b.getCreationDate())));
}
reply.setBucketList(myBucketList);
} catch (AmazonServiceException ex) {
LOG.debug("Got service error from backend: " + ex.getMessage(), ex);
throw S3ExceptionMapper.fromAWSJavaSDK(ex);
}
return reply;
}
/**
* Handles a HEAD request to the bucket. Just returns 200ok if bucket exists and user has access. Otherwise returns 404 if not found or 403 if no
* accesss.
*
* @param request
* @return
* @throws S3Exception
*/
@Override
public HeadBucketResponseType headBucket(HeadBucketType request) throws S3Exception {
HeadBucketResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
// call the storage manager to save the bucket to disk
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
com.amazonaws.services.s3.model.AccessControlList responseList = s3Client.getBucketAcl(request.getBucket());
reply.setBucket(request.getBucket());
} catch (AmazonServiceException ex) {
LOG.debug("Got service error from backend: " + ex.getMessage(), ex);
throw S3ExceptionMapper.fromAWSJavaSDK(ex);
}
return reply;
}
@Override
public CreateBucketResponseType createBucket(CreateBucketType request) throws S3Exception {
CreateBucketResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
Bucket responseBucket = s3Client.createBucket(request.getBucket());
// Save the owner info in response?
reply.setBucket(request.getBucket());
reply.setStatus(HttpResponseStatus.OK);
reply.setStatusMessage("OK");
} catch (AmazonServiceException ex) {
LOG.debug("Got service error from backend: " + ex.getMessage(), ex);
throw S3ExceptionMapper.fromAWSJavaSDK(ex);
}
return reply;
}
@Override
public DeleteBucketResponseType deleteBucket(DeleteBucketType request) throws S3Exception {
DeleteBucketResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
// call the storage manager to save the bucket to disk
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
s3Client.deleteBucket(request.getBucket());
} catch (AmazonServiceException ex) {
LOG.debug("Got service error from backend: " + ex.getMessage(), ex);
throw S3ExceptionMapper.fromAWSJavaSDK(ex);
}
return reply;
}
/**
* Should remove this, mostly pointless
*
* @param request
* @return
*/
private static UserPrincipal getRequestUser(ObjectStorageRequestType request) {
return request.getUser();
}
@Override
public GetBucketAccessControlPolicyResponseType getBucketAccessControlPolicy(GetBucketAccessControlPolicyType request) throws S3Exception {
GetBucketAccessControlPolicyResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
com.amazonaws.services.s3.model.AccessControlList acl = s3Client.getBucketAcl(request.getBucket());
reply.setAccessControlPolicy(sdkAclToEucaAcl(acl));
} catch (AmazonServiceException ex) {
LOG.debug("Got service error from backend: " + ex.getMessage(), ex);
throw S3ExceptionMapper.fromAWSJavaSDK(ex);
}
return reply;
}
@Override
public PutObjectResponseType putObject(PutObjectType request, InputStream inputData) throws S3Exception {
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
PutObjectResult result;
ObjectMetadata metadata = getS3ObjectMetadata(request);
// Set the acl to private.
PutObjectRequest putRequest =
new PutObjectRequest(request.getBucket(), request.getKey(), inputData, metadata).withCannedAcl(CannedAccessControlList.Private);
result = s3Client.putObject(putRequest);
PutObjectResponseType reply = request.getReply();
if (result == null) {
throw new InternalErrorException(null, "Null result from backend");
} else {
reply.setEtag(result.getETag());
reply.setVersionId(result.getVersionId());
reply.setLastModified(new Date());
}
return reply;
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
}
@Override
public PostObjectResponseType postObject(PostObjectType request) throws S3Exception {
throw new NotImplementedException("PostObject");
}
@Override
public DeleteObjectResponseType deleteObject(DeleteObjectType request) throws S3Exception {
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
DeleteObjectResponseType reply = request.getReply();
reply.setStatus(HttpResponseStatus.NO_CONTENT);
reply.setStatusMessage("NO CONTENT");
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
s3Client.deleteObject(request.getBucket(), request.getKey());
return reply;
} catch (AmazonServiceException ex) {
LOG.debug("Error from backend", ex);
throw S3ExceptionMapper.fromAWSJavaSDK(ex);
}
}
@Override
public ListBucketResponseType listBucket(ListBucketType request) throws S3Exception {
ListBucketResponseType reply = request.getReply();
UserPrincipal requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
ListObjectsRequest listRequest = new ListObjectsRequest();
listRequest.setBucketName(request.getBucket());
listRequest.setDelimiter(Strings.isNullOrEmpty(request.getDelimiter()) ? null : request.getDelimiter());
listRequest.setMarker(Strings.isNullOrEmpty(request.getMarker()) ? null : request.getMarker());
listRequest.setMaxKeys((request.getMaxKeys() == null ? null : Integer.parseInt(request.getMaxKeys())));
listRequest.setPrefix(Strings.isNullOrEmpty(request.getPrefix()) ? null : request.getPrefix());
ObjectListing response = s3Client.listObjects(listRequest);
/* Non-optional, must have non-null values */
reply.setName(request.getBucket());
reply.setMaxKeys(response.getMaxKeys());
reply.setMarker(response.getMarker() == null ? "" : response.getMarker());
reply.setPrefix(response.getPrefix() == null ? "" : response.getPrefix());
reply.setIsTruncated(response.isTruncated());
/* Optional */
reply.setNextMarker(response.getNextMarker());
reply.setDelimiter(response.getDelimiter());
if (reply.getContents() == null) {
reply.setContents(new ArrayList<ListEntry>());
}
if (reply.getCommonPrefixesList() == null) {
reply.setCommonPrefixesList(new ArrayList<CommonPrefixesEntry>());
}
for (S3ObjectSummary obj : response.getObjectSummaries()) {
// Add entry, note that the canonical user is set based on requesting user, not returned user
reply.getContents().add(new ListEntry(obj.getKey(), DateFormatter.dateToHeaderFormattedString(obj.getLastModified()), obj.getETag(),
obj.getSize(), getCanonicalUser(requestUser), obj.getStorageClass()));
}
if (response.getCommonPrefixes() != null && response.getCommonPrefixes().size() > 0) {
reply.setCommonPrefixesList(new ArrayList<CommonPrefixesEntry>());
for (String s : response.getCommonPrefixes()) {
reply.getCommonPrefixesList().add(new CommonPrefixesEntry(s));
}
}
return reply;
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
}
@Override
public GetObjectAccessControlPolicyResponseType getObjectAccessControlPolicy(GetObjectAccessControlPolicyType request) throws S3Exception {
GetObjectAccessControlPolicyResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
com.amazonaws.services.s3.model.AccessControlList acl = s3Client.getObjectAcl(request.getBucket(), request.getKey(), request.getVersionId());
reply.setAccessControlPolicy(sdkAclToEucaAcl(acl));
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
return reply;
}
@Override
public SetBucketAccessControlPolicyResponseType setBucketAccessControlPolicy(SetBucketAccessControlPolicyType request) throws S3Exception {
throw new NotImplementedException("?acl");
}
@Override
public SetObjectAccessControlPolicyResponseType setObjectAccessControlPolicy(SetObjectAccessControlPolicyType request) throws S3Exception {
throw new NotImplementedException("?acl");
}
protected void populateResponseMetadata(final ObjectStorageDataResponseType reply, final ObjectMetadata metadata) {
reply.setSize(metadata.getContentLength());
reply.setContentDisposition(metadata.getContentDisposition());
reply.setContentType(metadata.getContentType());
reply.setCacheControl(metadata.getCacheControl());
reply.setContentEncoding(metadata.getContentEncoding());
Date expires = metadata.getHttpExpiresDate();
reply.setExpires(DateFormatter.dateToHeaderFormattedString(expires));
reply.setEtag(metadata.getETag());
reply.setLastModified(metadata.getLastModified());
if (metadata.getUserMetadata() != null && metadata.getUserMetadata().size() > 0) {
if (reply.getMetaData() == null)
reply.setMetaData(new ArrayList<MetaDataEntry>());
for (String k : metadata.getUserMetadata().keySet()) {
reply.getMetaData().add(new MetaDataEntry(k, metadata.getUserMetadata().get(k)));
}
}
}
@Override
public GetObjectResponseType getObject(final GetObjectType request) throws S3Exception {
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
GetObjectRequest getRequest = new GetObjectRequest(request.getBucket(), request.getKey());
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
GetObjectResponseType reply = request.getReply();
S3Object response;
response = s3Client.getObject(getRequest);
populateResponseMetadata(reply, response.getObjectMetadata());
reply.setDataInputStream(response.getObjectContent());
return reply;
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
}
@Override
public GetObjectExtendedResponseType getObjectExtended(final GetObjectExtendedType request) throws S3Exception {
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
Long byteRangeStart = request.getByteRangeStart();
Long byteRangeEnd = request.getByteRangeEnd();
GetObjectRequest getRequest = new GetObjectRequest(request.getBucket(), request.getKey());
if (byteRangeStart != null && byteRangeEnd != null) {
getRequest.setRange(byteRangeStart, byteRangeEnd);
}
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
S3Object response = s3Client.getObject(getRequest);
GetObjectExtendedResponseType reply = request.getReply();
populateResponseMetadata(reply, response.getObjectMetadata());
reply.setDataInputStream(response.getObjectContent());
reply.setByteRangeStart(request.getByteRangeStart());
reply.setByteRangeEnd(request.getByteRangeEnd());
return reply;
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
}
@Override
public GetBucketLocationResponseType getBucketLocation(GetBucketLocationType request) throws S3Exception {
GetBucketLocationResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
String bucketLocation = s3Client.getBucketLocation(request.getBucket());
reply.getLocationConstraint().setLocation(bucketLocation);
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
return reply;
}
@Override
public CopyObjectResponseType copyObject(CopyObjectType request) throws S3Exception {
CopyObjectResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
String sourceBucket = request.getSourceBucket();
String sourceKey = request.getSourceObject();
String sourceVersionId = request.getSourceVersionId().equals(ObjectStorageProperties.NULL_VERSION_ID) ? null : request.getSourceVersionId();
String destinationBucket = request.getDestinationBucket();
String destinationKey = request.getDestinationObject();
String copyIfMatch = request.getCopySourceIfMatch();
String copyIfNoneMatch = request.getCopySourceIfNoneMatch();
Date copyIfUnmodifiedSince = request.getCopySourceIfUnmodifiedSince();
Date copyIfModifiedSince = request.getCopySourceIfModifiedSince();
try {
CopyObjectRequest copyRequest = new CopyObjectRequest(sourceBucket, sourceKey, sourceVersionId, destinationBucket, destinationKey);
copyRequest.setModifiedSinceConstraint(copyIfModifiedSince);
copyRequest.setUnmodifiedSinceConstraint(copyIfUnmodifiedSince);
if (copyIfMatch != null) {
List<String> copyIfMatchConstraint = new ArrayList<String>();
copyIfMatchConstraint.add(copyIfMatch);
copyRequest.setMatchingETagConstraints(copyIfMatchConstraint);
}
if (copyIfNoneMatch != null) {
List<String> copyIfNoneMatchConstraint = new ArrayList<String>();
copyIfNoneMatchConstraint.add(copyIfNoneMatch);
copyRequest.setNonmatchingETagConstraints(copyIfNoneMatchConstraint);
}
// TODO: Need to set canned ACL if specified
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
CopyObjectResult result = s3Client.copyObject(copyRequest);
reply.setEtag(result.getETag());
reply.setLastModified(DateFormatter.dateToListingFormattedString(result.getLastModifiedDate()));
String destinationVersionId = result.getVersionId();
if (destinationVersionId != null) {
reply.setCopySourceVersionId(sourceVersionId);
reply.setVersionId(destinationVersionId);
}
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
return reply;
}
/*
* NOTE: bucket logging grants don't work because there is no way to specify them via the S3 Java SDK. Need to add that functionality ourselves if
* we want it on the backend directly
*
* (non-Javadoc)
*
* @see
* com.eucalyptus.objectstorage.ObjectStorageProviderClient#setBucketLoggingStatus(com.eucalyptus.objectstorage.msgs.SetBucketLoggingStatusType)
*/
@Override
public SetBucketLoggingStatusResponseType setBucketLoggingStatus(SetBucketLoggingStatusType request) throws S3Exception {
SetBucketLoggingStatusResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
BucketLoggingConfiguration config = new BucketLoggingConfiguration();
LoggingEnabled requestConfig = request.getLoggingEnabled();
config.setDestinationBucketName(requestConfig == null ? null : requestConfig.getTargetBucket());
config.setLogFilePrefix(requestConfig == null ? null : requestConfig.getTargetPrefix());
SetBucketLoggingConfigurationRequest loggingRequest = new SetBucketLoggingConfigurationRequest(request.getBucket(), config);
s3Client.setBucketLoggingConfiguration(loggingRequest);
reply.setStatus(HttpResponseStatus.OK);
reply.setStatusMessage("OK");
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
return reply;
}
@Override
public GetBucketLoggingStatusResponseType getBucketLoggingStatus(GetBucketLoggingStatusType request) throws S3Exception {
GetBucketLoggingStatusResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
BucketLoggingConfiguration loggingConfig = s3Client.getBucketLoggingConfiguration(request.getBucket());
LoggingEnabled loggingEnabled = new LoggingEnabled();
if (loggingConfig == null || !loggingConfig.isLoggingEnabled()) {
// Do nothing, logging is disabled
} else {
// S3 SDK does not provide a way to fetch the grants on the destination logging
loggingEnabled.setTargetBucket(loggingConfig.getDestinationBucketName());
loggingEnabled.setTargetPrefix(loggingConfig.getLogFilePrefix());
}
reply.setLoggingEnabled(loggingEnabled);
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
return reply;
}
@Override
public GetBucketVersioningStatusResponseType getBucketVersioningStatus(GetBucketVersioningStatusType request) throws S3Exception {
GetBucketVersioningStatusResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
BucketVersioningConfiguration versioning = s3Client.getBucketVersioningConfiguration(request.getBucket());
reply.setVersioningStatus(versioning.getStatus());
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
return reply;
}
@Override
public SetBucketVersioningStatusResponseType setBucketVersioningStatus(SetBucketVersioningStatusType request) throws S3Exception {
SetBucketVersioningStatusResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
BucketVersioningConfiguration config = new BucketVersioningConfiguration().withStatus(request.getVersioningStatus());
SetBucketVersioningConfigurationRequest configRequest = new SetBucketVersioningConfigurationRequest(request.getBucket(), config);
s3Client.setBucketVersioningConfiguration(configRequest);
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
return reply;
}
@Override
public ListVersionsResponseType listVersions(ListVersionsType request) throws S3Exception {
ListVersionsResponseType reply = request.getReply();
UserPrincipal requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
ListVersionsRequest listVersionsRequest = new ListVersionsRequest(request.getBucket(), request.getPrefix(), request.getKeyMarker(),
request.getVersionIdMarker(), request.getDelimiter(), Integer.parseInt(request.getMaxKeys()));
VersionListing result = s3Client.listVersions(listVersionsRequest);
CanonicalUser owner = getCanonicalUser(requestUser);
// Populate result to euca
reply.setBucket(request.getBucket());
reply.setMaxKeys(result.getMaxKeys());
reply.setDelimiter(result.getDelimiter());
reply.setNextKeyMarker(result.getNextKeyMarker());
reply.setNextVersionIdMarker(result.getNextVersionIdMarker());
reply.setIsTruncated(result.isTruncated());
reply.setVersionIdMarker(result.getVersionIdMarker());
reply.setKeyMarker(result.getKeyMarker());
if (result.getCommonPrefixes() != null && result.getCommonPrefixes().size() > 0) {
reply.setCommonPrefixesList(new ArrayList<CommonPrefixesEntry>());
for (String s : result.getCommonPrefixes()) {
reply.getCommonPrefixesList().add(new CommonPrefixesEntry(s));
}
}
ArrayList<KeyEntry> versions = new ArrayList<>();
VersionEntry v;
DeleteMarkerEntry d;
for (S3VersionSummary summary : result.getVersionSummaries()) {
if (!summary.isDeleteMarker()) {
v = new VersionEntry();
v.setKey(summary.getKey());
v.setVersionId(summary.getVersionId());
v.setLastModified(DateFormatter.dateToHeaderFormattedString(summary.getLastModified()));
v.setEtag(summary.getETag());
v.setIsLatest(summary.isLatest());
v.setOwner(owner);
v.setSize(summary.getSize());
versions.add(v);
} else {
d = new DeleteMarkerEntry();
d.setIsLatest(summary.isLatest());
d.setKey(summary.getKey());
d.setLastModified(DateFormatter.dateToHeaderFormattedString(summary.getLastModified()));
d.setOwner(owner);
d.setVersionId(summary.getVersionId());
versions.add(d);
}
}
// Again, this is wrong, should be a single listing
reply.setKeyEntries(versions);
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
return reply;
}
@Override
public DeleteVersionResponseType deleteVersion(DeleteVersionType request) throws S3Exception {
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
s3Client.deleteVersion(request.getBucket(), request.getKey(), request.getVersionId());
DeleteVersionResponseType reply = request.getReply();
reply.setStatus(HttpResponseStatus.NO_CONTENT);
reply.setStatusMessage("NO CONTENT");
return reply;
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
}
@Override
public HeadObjectResponseType headObject(final HeadObjectType request) throws S3Exception {
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
GetObjectMetadataRequest getMetadataRequest = new GetObjectMetadataRequest(request.getBucket(), request.getKey());
getMetadataRequest.setVersionId(request.getVersionId());
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
ObjectMetadata metadata;
metadata = s3Client.getObjectMetadata(getMetadataRequest);
HeadObjectResponseType reply = request.getReply();
populateResponseMetadata(reply, metadata);
return reply;
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
}
@Override
public InitiateMultipartUploadResponseType initiateMultipartUpload(InitiateMultipartUploadType request) throws S3Exception {
InitiateMultipartUploadResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
String bucketName = request.getBucket();
String key = request.getKey();
InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(bucketName, key);
ObjectMetadata metadata = new ObjectMetadata();
for (MetaDataEntry meta : request.getMetaData()) {
metadata.addUserMetadata(meta.getName(), meta.getValue());
}
initiateMultipartUploadRequest.setObjectMetadata(metadata);
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
InitiateMultipartUploadResult result = s3Client.initiateMultipartUpload(initiateMultipartUploadRequest);
reply.setUploadId(result.getUploadId());
reply.setBucket(bucketName);
reply.setKey(key);
return reply;
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
}
@Override
public UploadPartResponseType uploadPart(UploadPartType request, InputStream dataContent) throws S3Exception {
String bucketName = request.getBucket();
String key = request.getKey();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
UploadPartResult result;
UploadPartRequest uploadPartRequest = new UploadPartRequest();
uploadPartRequest.setBucketName(bucketName);
uploadPartRequest.setKey(key);
uploadPartRequest.setInputStream(dataContent);
uploadPartRequest.setUploadId(request.getUploadId());
uploadPartRequest.setPartNumber(Integer.valueOf(request.getPartNumber()));
uploadPartRequest.setMd5Digest(request.getContentMD5());
uploadPartRequest.setPartSize(Long.valueOf(request.getContentLength()));
try {
result = s3Client.uploadPart(uploadPartRequest);
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
UploadPartResponseType reply = request.getReply();
reply.setEtag(result.getETag());
reply.setLastModified(new Date());
return reply;
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
}
@Override
public CompleteMultipartUploadResponseType completeMultipartUpload(CompleteMultipartUploadType request) throws S3Exception {
CompleteMultipartUploadResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
String bucketName = request.getBucket();
String key = request.getKey();
String uploadId = request.getUploadId();
List<Part> parts = request.getParts();
List<PartETag> partETags = new ArrayList<>();
for (Part part : parts) {
PartETag partETag = new PartETag(part.getPartNumber(), part.getEtag());
partETags.add(partETag);
}
CompleteMultipartUploadRequest multipartRequest = new CompleteMultipartUploadRequest(bucketName, key, uploadId, partETags);
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
CompleteMultipartUploadResult result = s3Client.completeMultipartUpload(multipartRequest);
reply.setEtag(result.getETag());
reply.setBucket(bucketName);
reply.setKey(key);
reply.setLocation(result.getLocation());
reply.setLastModified(new Date());
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
return reply;
}
@Override
public AbortMultipartUploadResponseType abortMultipartUpload(AbortMultipartUploadType request) throws S3Exception {
AbortMultipartUploadResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
String bucketName = request.getBucket();
String key = request.getKey();
String uploadId = request.getUploadId();
AbortMultipartUploadRequest abortMultipartUploadRequest = new AbortMultipartUploadRequest(bucketName, key, uploadId);
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
s3Client.abortMultipartUpload(abortMultipartUploadRequest);
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
return reply;
}
@Override
public ListPartsResponseType listParts(ListPartsType request) throws S3Exception {
ListPartsResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
String bucketName = request.getBucket();
String key = request.getKey();
String uploadId = request.getUploadId();
ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName, key, uploadId);
if (request.getMaxParts() != null) {
listPartsRequest.setMaxParts(Integer.parseInt(request.getMaxParts()));
}
if (request.getPartNumberMarker() != null) {
listPartsRequest.setPartNumberMarker(Integer.parseInt(request.getPartNumberMarker()));
}
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
PartListing listing = s3Client.listParts(listPartsRequest);
reply.setBucket(bucketName);
reply.setKey(key);
reply.setUploadId(uploadId);
Initiator initiator = new Initiator(listing.getInitiator().getId(), listing.getInitiator().getDisplayName());
reply.setInitiator(initiator);
CanonicalUser owner = new CanonicalUser(listing.getOwner().getId(), listing.getOwner().getDisplayName());
reply.setOwner(owner);
reply.setStorageClass(listing.getStorageClass());
reply.setPartNumberMarker(listing.getPartNumberMarker());
reply.setNextPartNumberMarker(listing.getNextPartNumberMarker());
reply.setMaxParts(listing.getMaxParts());
reply.setIsTruncated(listing.isTruncated());
List<PartSummary> parts = listing.getParts();
List<Part> replyParts = reply.getParts();
for (PartSummary part : parts) {
replyParts.add(new Part(part.getPartNumber(), part.getETag(), part.getLastModified(), part.getSize()));
}
} catch (AmazonServiceException ex) {
LOG.debug("Got service error from backend: " + ex.getMessage(), ex);
throw S3ExceptionMapper.fromAWSJavaSDK(ex);
}
return reply;
}
@Override
public ListMultipartUploadsResponseType listMultipartUploads(ListMultipartUploadsType request) throws S3Exception {
ListMultipartUploadsResponseType reply = request.getReply();
User requestUser = getRequestUser(request);
OsgInternalS3Client internalS3Client = null;
String bucketName = request.getBucket();
ListMultipartUploadsRequest listMultipartUploadsRequest = new ListMultipartUploadsRequest(bucketName);
listMultipartUploadsRequest.setMaxUploads(Integer.parseInt(request.getMaxUploads()));
listMultipartUploadsRequest.setKeyMarker(request.getKeyMarker());
listMultipartUploadsRequest.setDelimiter(request.getDelimiter());
listMultipartUploadsRequest.setPrefix(request.getPrefix());
listMultipartUploadsRequest.setUploadIdMarker(request.getUploadIdMarker());
try {
internalS3Client = getS3Client(requestUser);
AmazonS3Client s3Client = internalS3Client.getS3Client();
MultipartUploadListing listing = s3Client.listMultipartUploads(listMultipartUploadsRequest);
reply.setBucket(listing.getBucketName());
reply.setKeyMarker(listing.getKeyMarker());
reply.setUploadIdMarker(listing.getUploadIdMarker());
reply.setNextKeyMarker(listing.getNextKeyMarker());
reply.setNextUploadIdMarker(listing.getNextUploadIdMarker());
reply.setMaxUploads(listing.getMaxUploads());
reply.setIsTruncated(listing.isTruncated());
reply.setPrefix(listing.getPrefix());
reply.setDelimiter(listing.getDelimiter());
List<String> commonPrefixes = listing.getCommonPrefixes();
List<MultipartUpload> multipartUploads = listing.getMultipartUploads();
List<com.eucalyptus.storage.msgs.s3.Upload> uploads = reply.getUploads();
List<CommonPrefixesEntry> prefixes = reply.getCommonPrefixes();
for (MultipartUpload multipartUpload : multipartUploads) {
uploads.add(new com.eucalyptus.storage.msgs.s3.Upload(multipartUpload.getKey(), multipartUpload.getUploadId(),
new Initiator(multipartUpload.getInitiator().getId(), multipartUpload.getInitiator().getDisplayName()),
new CanonicalUser(multipartUpload.getOwner().getId(), multipartUpload.getOwner().getDisplayName()), multipartUpload.getStorageClass(),
multipartUpload.getInitiated()));
}
for (String commonPrefix : commonPrefixes) {
prefixes.add(new CommonPrefixesEntry(commonPrefix));
}
return reply;
} catch (AmazonServiceException e) {
LOG.debug("Error from backend", e);
throw S3ExceptionMapper.fromAWSJavaSDK(e);
}
}
}