~ubuntu-branches/ubuntu/raring/eucalyptus/raring

« back to all changes in this revision

Viewing changes to clc/modules/walrus/src/main/java/edu/ucsb/eucalyptus/cloud/ws/WalrusManager.java

  • Committer: Package Import Robot
  • Author(s): Brian Thomason
  • Date: 2011-11-29 13:17:52 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 185.
  • Revision ID: package-import@ubuntu.com-20111129131752-rq31al3ntutv2vvl
Tags: upstream-3.0.999beta1
ImportĀ upstreamĀ versionĀ 3.0.999beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
 *    SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
54
54
 *    IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
55
55
 *    BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
56
 
 *    THE REGENTSā€™ DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
 
56
 *    THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
57
57
 *    OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
58
58
 *    WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
59
59
 *    ANY SUCH LICENSES OR RIGHTS.
79
79
import java.util.List;
80
80
import java.util.UUID;
81
81
 
 
82
import javax.persistence.RollbackException;
 
83
 
82
84
import org.apache.log4j.Logger;
83
85
import org.apache.tools.ant.util.DateUtils;
 
86
import org.bouncycastle.util.encoders.Base64;
 
87
import org.hibernate.exception.ConstraintViolationException;
 
88
import org.jboss.cache.commands.tx.RollbackCommand;
84
89
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
85
90
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
86
91
import org.jboss.netty.handler.codec.http.HttpVersion;
 
92
import org.xbill.DNS.Name;
87
93
 
88
 
import com.eucalyptus.auth.NoSuchUserException;
89
 
import com.eucalyptus.auth.Users;
90
 
import com.eucalyptus.auth.crypto.Digest;
 
94
import com.eucalyptus.auth.Accounts;
 
95
import com.eucalyptus.auth.AuthException;
 
96
import com.eucalyptus.auth.Permissions;
 
97
import com.eucalyptus.auth.policy.PolicySpec;
 
98
import com.eucalyptus.auth.principal.Account;
91
99
import com.eucalyptus.auth.principal.User;
92
100
import com.eucalyptus.auth.util.Hashes;
93
 
import com.eucalyptus.bootstrap.Component;
 
101
import com.eucalyptus.component.Components;
 
102
import com.eucalyptus.context.Context;
 
103
import com.eucalyptus.context.Contexts;
 
104
import com.eucalyptus.crypto.Digest;
94
105
import com.eucalyptus.entities.EntityWrapper;
 
106
import com.eucalyptus.reporting.event.S3Event;
 
107
import com.eucalyptus.reporting.queue.*;
 
108
import com.eucalyptus.reporting.queue.QueueFactory.QueueIdentifier;
95
109
import com.eucalyptus.util.EucalyptusCloudException;
 
110
import com.eucalyptus.util.Exceptions;
 
111
import com.eucalyptus.util.Lookups;
96
112
import com.eucalyptus.util.WalrusProperties;
97
113
import com.eucalyptus.ws.client.ServiceDispatcher;
98
114
import com.eucalyptus.ws.handlers.WalrusRESTBinding;
102
118
import edu.ucsb.eucalyptus.cloud.BucketAlreadyOwnedByYouException;
103
119
import edu.ucsb.eucalyptus.cloud.BucketLogData;
104
120
import edu.ucsb.eucalyptus.cloud.BucketNotEmptyException;
 
121
import edu.ucsb.eucalyptus.cloud.ContentMismatchException;
105
122
import edu.ucsb.eucalyptus.cloud.EntityTooLargeException;
106
123
import edu.ucsb.eucalyptus.cloud.InlineDataTooLargeException;
107
124
import edu.ucsb.eucalyptus.cloud.InvalidBucketNameException;
195
212
import edu.ucsb.eucalyptus.util.WalrusDataMessenger;
196
213
import edu.ucsb.eucalyptus.util.WalrusDataQueue;
197
214
import edu.ucsb.eucalyptus.util.WalrusMonitor;
 
215
import edu.ucsb.eucalyptus.util.SystemUtil;
 
216
import com.eucalyptus.system.Threads;
 
217
import com.eucalyptus.component.id.Dns;
 
218
import com.eucalyptus.component.id.Walrus;
198
219
 
199
220
public class WalrusManager {
200
221
        private static Logger LOG = Logger.getLogger(WalrusManager.class);
218
239
        }
219
240
 
220
241
        public void check() throws EucalyptusCloudException {
221
 
                File bukkitDir = new File(WalrusInfo.getWalrusInfo().getStorageDir());
222
 
                if (!bukkitDir.exists()) {
223
 
                        if (!bukkitDir.mkdirs()) {
 
242
                String bukkitDir = WalrusInfo.getWalrusInfo().getStorageDir();
 
243
                File bukkits = new File(WalrusInfo.getWalrusInfo().getStorageDir());
 
244
                if (!bukkits.exists()) {
 
245
                        if (!bukkits.mkdirs()) {
224
246
                                LOG.fatal("Unable to make bucket root directory: "
225
 
                                                + WalrusInfo.getWalrusInfo().getStorageDir());
 
247
                                                + bukkitDir);
226
248
                                throw new EucalyptusCloudException(
227
 
                                "Invalid bucket root directory");
 
249
                                                "Invalid bucket root directory");
228
250
                        }
229
 
                } else if (!bukkitDir.canWrite()) {
 
251
                } else if (!bukkits.canWrite()) {
230
252
                        LOG.fatal("Cannot write to bucket root directory: "
231
 
                                        + WalrusInfo.getWalrusInfo().getStorageDir());
 
253
                                        + bukkitDir);
232
254
                        throw new EucalyptusCloudException("Invalid bucket root directory");
233
255
                }
234
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
235
 
                BucketInfo bucketInfo = new BucketInfo();
236
 
                List<BucketInfo> bucketInfos = db.query(bucketInfo);
237
 
                for (BucketInfo bucket : bucketInfos) {
238
 
                        if (!storageManager.bucketExists(bucket.getBucketName()))
239
 
                                bucket.setHidden(true);
240
 
                        else
241
 
                                bucket.setHidden(false);
 
256
                try {
 
257
                        SystemUtil.setEucaReadWriteOnly(bukkitDir);
 
258
                } catch (EucalyptusCloudException ex) {
 
259
                        LOG.fatal(ex);
242
260
                }
243
 
                db.commit();
244
261
        }
245
262
 
246
263
        public ListAllMyBucketsResponseType listAllMyBuckets(
247
264
                        ListAllMyBucketsType request) throws EucalyptusCloudException {
248
265
                ListAllMyBucketsResponseType reply = (ListAllMyBucketsResponseType) request
249
 
                .getReply();
250
 
                String userId = request.getUserId();
251
 
 
252
 
                if (userId == null) {
253
 
                        throw new AccessDeniedException("no such user");
254
 
                }
255
 
 
256
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
257
 
                BucketInfo searchBucket = new BucketInfo();
258
 
                searchBucket.setOwnerId(userId);
259
 
                searchBucket.setHidden(false);
260
 
                List<BucketInfo> bucketInfoList = db.query(searchBucket);
261
 
 
262
 
                ArrayList<BucketListEntry> buckets = new ArrayList<BucketListEntry>();
263
 
 
264
 
                for (BucketInfo bucketInfo : bucketInfoList) {
265
 
                        if (request.isAdministrator()) {
266
 
                                EntityWrapper<WalrusSnapshotInfo> dbSnap = db
267
 
                                .recast(WalrusSnapshotInfo.class);
268
 
                                WalrusSnapshotInfo walrusSnapInfo = new WalrusSnapshotInfo();
269
 
                                walrusSnapInfo.setSnapshotBucket(bucketInfo.getBucketName());
270
 
                                List<WalrusSnapshotInfo> walrusSnaps = dbSnap
271
 
                                .query(walrusSnapInfo);
272
 
                                if (walrusSnaps.size() > 0)
273
 
                                        continue;
274
 
                        }
275
 
                        buckets.add(new BucketListEntry(bucketInfo.getBucketName(),
276
 
                                        DateUtils.format(bucketInfo.getCreationDate().getTime(),
277
 
                                                        DateUtils.ISO8601_DATETIME_PATTERN)
278
 
                                                        + ".000Z"));
279
 
                }
 
266
                                .getReply();
 
267
                Context ctx = Contexts.lookup();
 
268
                Account account = ctx.getAccount();
 
269
 
 
270
                if (account == null) {
 
271
                        throw new AccessDeniedException("no such account");
 
272
                }
 
273
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
280
274
                try {
281
 
                        CanonicalUserType owner = new CanonicalUserType(Users
282
 
                                        .lookupUser(userId).getQueryId(), userId);
283
 
                        ListAllMyBucketsList bucketList = new ListAllMyBucketsList();
284
 
                        reply.setOwner(owner);
285
 
                        bucketList.setBuckets(buckets);
286
 
                        reply.setBucketList(bucketList);
287
 
                } catch (Exception ex) {
288
 
                        db.rollback();
289
 
                        LOG.error(ex);
290
 
                        throw new AccessDeniedException("User: " + userId + " not found");
 
275
                        BucketInfo searchBucket = new BucketInfo();
 
276
                        searchBucket.setOwnerId(account.getAccountNumber());
 
277
                        searchBucket.setHidden(false);
 
278
                        List<BucketInfo> bucketInfoList = db.query(searchBucket);
 
279
 
 
280
                        ArrayList<BucketListEntry> buckets = new ArrayList<BucketListEntry>();
 
281
 
 
282
                        for (BucketInfo bucketInfo : bucketInfoList) {
 
283
                                if (ctx.hasAdministrativePrivileges() ||
 
284
                                                Lookups.checkPrivilege(PolicySpec.S3_LISTALLMYBUCKETS,
 
285
                                                                PolicySpec.VENDOR_S3,
 
286
                                                                PolicySpec.S3_RESOURCE_BUCKET,
 
287
                                                                bucketInfo.getBucketName(),
 
288
                                                                bucketInfo.getOwnerId())) {                                             
 
289
                                        EntityWrapper<WalrusSnapshotInfo> dbSnap = EntityWrapper.get(WalrusSnapshotInfo.class);
 
290
                                        try {
 
291
                                                WalrusSnapshotInfo walrusSnapInfo = new WalrusSnapshotInfo();
 
292
                                                walrusSnapInfo.setSnapshotBucket(bucketInfo.getBucketName());
 
293
                                                List<WalrusSnapshotInfo> walrusSnaps = dbSnap
 
294
                                                                .query(walrusSnapInfo);
 
295
                                                dbSnap.commit();
 
296
                                                if (walrusSnaps.size() > 0)
 
297
                                                        continue;
 
298
                                        } catch (Exception eee) {
 
299
                                                LOG.debug(eee, eee);
 
300
                                                dbSnap.rollback();
 
301
                                        }
 
302
                                }
 
303
                                buckets.add(new BucketListEntry(bucketInfo.getBucketName(),
 
304
                                                DateUtils.format(bucketInfo.getCreationDate().getTime(),
 
305
                                                                DateUtils.ISO8601_DATETIME_PATTERN)
 
306
                                                                + ".000Z"));
 
307
                        }
 
308
                        try {
 
309
                                CanonicalUserType owner = new CanonicalUserType(account.getName(), account.getAccountNumber());
 
310
                                ListAllMyBucketsList bucketList = new ListAllMyBucketsList();
 
311
                                reply.setOwner(owner);
 
312
                                bucketList.setBuckets(buckets);
 
313
                                reply.setBucketList(bucketList);
 
314
                        } catch (Exception ex) {
 
315
                                db.rollback();
 
316
                                LOG.error(ex);
 
317
                                throw new AccessDeniedException("Account: " + account.getName() + " not found", ex);
 
318
                        }
 
319
                        db.commit();
 
320
                } catch (EucalyptusCloudException e) {
 
321
                        db.rollback();
 
322
                        throw e;
 
323
                } catch (Exception e) {
 
324
                        LOG.debug(e, e);
 
325
                        db.rollback();
291
326
                }
292
 
                db.commit();
293
327
                return reply;
294
328
        }
295
329
 
296
330
        public CreateBucketResponseType createBucket(CreateBucketType request)
297
 
        throws EucalyptusCloudException {
 
331
                        throws EucalyptusCloudException {
298
332
                CreateBucketResponseType reply = (CreateBucketResponseType) request
299
 
                .getReply();
300
 
                String userId = request.getUserId();
 
333
                                .getReply();
 
334
                Context ctx = Contexts.lookup();
 
335
                Account account = ctx.getAccount();
301
336
 
302
337
                String bucketName = request.getBucket();
303
338
                String locationConstraint = request.getLocationConstraint();
304
339
 
305
 
                if (userId == null) {
 
340
                if (account == null) {
306
341
                        throw new AccessDeniedException("Bucket", bucketName);
307
342
                }
308
343
 
309
344
                AccessControlListType accessControlList = request
310
 
                .getAccessControlList();
 
345
                                .getAccessControlList();
311
346
                if (accessControlList == null) {
312
347
                        accessControlList = new AccessControlListType();
313
348
                }
315
350
                if(!checkBucketName(bucketName))
316
351
                        throw new InvalidBucketNameException(bucketName);
317
352
 
318
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
353
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
319
354
 
320
355
                if (WalrusProperties.shouldEnforceUsageLimits
321
 
                                && !request.isAdministrator()) {
 
356
                                && !Contexts.lookup().hasAdministrativePrivileges()) {
322
357
                        BucketInfo searchBucket = new BucketInfo();
323
 
                        searchBucket.setOwnerId(userId);
 
358
                        searchBucket.setOwnerId(account.getAccountNumber());
324
359
                        List<BucketInfo> bucketList = db.query(searchBucket);
325
 
                        if (bucketList.size() >= WalrusInfo.getWalrusInfo().getStorageMaxBucketsPerUser()) {
 
360
                        if (bucketList.size() >= WalrusInfo.getWalrusInfo().getStorageMaxBucketsPerAccount()) {
326
361
                                db.rollback();
327
362
                                throw new TooManyBucketsException(bucketName);
328
363
                        }
332
367
                List<BucketInfo> bucketList = db.query(bucketInfo);
333
368
 
334
369
                if (bucketList.size() > 0) {
335
 
                        if (bucketList.get(0).getOwnerId().equals(userId)) {
 
370
                        if (bucketList.get(0).getOwnerId().equals(account.getAccountNumber())) {
336
371
                                // bucket already exists and you created it
337
372
                                db.rollback();
338
373
                                throw new BucketAlreadyOwnedByYouException(bucketName);
341
376
                        db.rollback();
342
377
                        throw new BucketAlreadyExistsException(bucketName);
343
378
                } else {
344
 
                        // create bucket and set its acl
345
 
                        BucketInfo bucket = new BucketInfo(userId, bucketName, new Date());
346
 
                        ArrayList<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
347
 
                        bucket.addGrants(userId, grantInfos, accessControlList);
348
 
                        bucket.setGrants(grantInfos);
349
 
                        bucket.setBucketSize(0L);
350
 
                        bucket.setLoggingEnabled(false);
351
 
                        bucket.setVersioning(WalrusProperties.VersioningStatus.Disabled
352
 
                                        .toString());
353
 
                        bucket.setHidden(false);
354
 
                        if (locationConstraint != null)
355
 
                                bucket.setLocation(locationConstraint);
356
 
                        else
357
 
                                bucket.setLocation("US");
358
 
                        db.add(bucket);
359
 
                        // call the storage manager to save the bucket to disk
360
 
                        try {
361
 
                                storageManager.createBucket(bucketName);
362
 
                                if (WalrusProperties.trackUsageStatistics)
363
 
                                        walrusStatistics.incrementBucketCount();
364
 
                        } catch (IOException ex) {
365
 
                                LOG.error(ex);
 
379
                        if (ctx.hasAdministrativePrivileges() || (
 
380
                                        Permissions.isAuthorized(PolicySpec.VENDOR_S3,
 
381
                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
382
                                                        "",
 
383
                                                        ctx.getAccount(),
 
384
                                                        PolicySpec.S3_CREATEBUCKET,
 
385
                                                        ctx.getUser()) &&
 
386
                                                        Permissions.canAllocate(PolicySpec.VENDOR_S3,
 
387
                                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
388
                                                                        "",
 
389
                                                                        PolicySpec.S3_CREATEBUCKET,
 
390
                                                                        ctx.getUser(),
 
391
                                                                        1L))) {
 
392
                                // create bucket and set its acl
 
393
                                BucketInfo bucket = new BucketInfo(account.getAccountNumber(), ctx.getUser( ).getUserId( ), bucketName, new Date());
 
394
                                ArrayList<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
 
395
                                bucket.addGrants(account.getAccountNumber(), grantInfos, accessControlList);
 
396
                                bucket.setGrants(grantInfos);
 
397
                                bucket.setBucketSize(0L);
 
398
                                bucket.setLoggingEnabled(false);
 
399
                                bucket.setVersioning(WalrusProperties.VersioningStatus.Disabled
 
400
                                                .toString());
 
401
                                bucket.setHidden(false);
 
402
                                if (locationConstraint != null)
 
403
                                        bucket.setLocation(locationConstraint);
 
404
                                else
 
405
                                        bucket.setLocation("US");
 
406
                                // call the storage manager to save the bucket to disk
 
407
                                try {
 
408
                                        db.add(bucket);
 
409
                                        db.commit();
 
410
                                        storageManager.createBucket(bucketName);
 
411
                                        if (WalrusProperties.trackUsageStatistics)
 
412
                                                walrusStatistics.incrementBucketCount();
 
413
                                } catch (IOException ex) {
 
414
                                        LOG.error(ex, ex);
 
415
                                        throw new BucketAlreadyExistsException(bucketName);
 
416
                                } catch (Exception ex) {
 
417
                                        LOG.error(ex, ex);
 
418
                                        db.rollback();
 
419
                                        if (Exceptions.isCausedBy(ex, ConstraintViolationException.class)) {
 
420
                                                throw new BucketAlreadyExistsException(bucketName);     
 
421
                                        } else {
 
422
                                                throw new EucalyptusCloudException("Unable to create bucket: " + bucketName);                                           
 
423
                                        }
 
424
                                }
 
425
                                QueueSender queueSender = QueueFactory.getInstance().getSender(QueueIdentifier.S3);
 
426
                                queueSender.send(new S3Event(true, ctx.getUser().getUserId(),
 
427
                                        ctx.getUser().getName(), ctx.getAccount().getAccountNumber(),
 
428
                                        ctx.getAccount().getName()));
 
429
 
 
430
                        } else {
 
431
                                LOG.error( "Not authorized to create bucket by " + ctx.getUserFullName( ) );
366
432
                                db.rollback();
367
 
                                throw new EucalyptusCloudException("Unable to create bucket: "
368
 
                                                + bucketName);
369
 
                        }
370
 
                }
371
 
                db.commit();
372
 
 
373
 
                if(WalrusProperties.enableVirtualHosting) {
374
 
                        if(checkDNSNaming(bucketName)) {
375
 
                                UpdateARecordType updateARecord = new UpdateARecordType();
376
 
                                updateARecord.setUserId(userId);
377
 
                                URI walrusUri;
378
 
                                String address = null;
379
 
                                try {
380
 
                                        walrusUri = new URI(SystemConfiguration.getWalrusUrl());
381
 
                                        address = walrusUri.getHost();
382
 
                                } catch (URISyntaxException e) {
383
 
                                        throw new EucalyptusCloudException("Could not get Walrus URL");
384
 
                                }
385
 
                                String zone = WalrusProperties.WALRUS_SUBDOMAIN + ".";
386
 
                                updateARecord.setAddress(address);
387
 
                                updateARecord.setName(bucketName + "." + zone);
388
 
                                updateARecord.setTtl(604800);
389
 
                                updateARecord.setZone(zone);
390
 
                                try {
391
 
                                        ServiceDispatcher.lookupSingle(Component.dns).send(updateARecord);
392
 
                                        LOG.info("Mapping " + updateARecord.getName() + " to " + address);
393
 
                                } catch(Exception ex) {
394
 
                                        LOG.error("Could not update DNS record", ex);
395
 
                                }
396
 
                        } else {
397
 
                                LOG.error("Bucket: " + bucketName + " fails to meet DNS requirements. Unable to create DNS mapping.");
398
 
                        }
399
 
                }
400
 
 
 
433
                                throw new AccessDeniedException("Bucket", bucketName);
 
434
                        }
 
435
                }
401
436
                reply.setBucket(bucketName);
402
437
                return reply;
403
438
        }
404
439
 
405
440
        private boolean checkBucketName(String bucketName) {
406
 
                if(!(bucketName.matches("^[A-Za-z0-9].*") || bucketName.contains(".") || 
407
 
                                bucketName.contains("-")))
 
441
                if(!bucketName.matches("^[A-Za-z0-9][A-Za-z0-9._-]+"))
408
442
                        return false;
409
443
                if(bucketName.length() < 3 || bucketName.length() > 255)
410
444
                        return false;
428
462
        }
429
463
 
430
464
        private boolean checkDNSNaming(String bucketName) {
431
 
                if(bucketName.contains("_"))
 
465
                if(!bucketName.matches("^[a-z0-9][a-z0-9.-]+"))
432
466
                        return false;
433
467
                if(bucketName.length() < 3 || bucketName.length() > 63)
434
468
                        return false;
435
469
                if(bucketName.endsWith("-"))
436
470
                        return false;
 
471
                if(bucketName.contains(".."))
 
472
                        return false;
437
473
                if(bucketName.contains("-." ) || bucketName.contains(".-"))
438
474
                        return false;
439
475
                return true;
442
478
        public DeleteBucketResponseType deleteBucket(DeleteBucketType request) throws EucalyptusCloudException {
443
479
                DeleteBucketResponseType reply = (DeleteBucketResponseType) request.getReply();
444
480
                String bucketName = request.getBucket();
445
 
                String userId = request.getUserId();
446
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
481
                Context ctx = Contexts.lookup();
 
482
                Account account = ctx.getAccount();
 
483
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
447
484
                BucketInfo searchBucket = new BucketInfo(bucketName);
448
485
                List<BucketInfo> bucketList = db.query(searchBucket);
449
486
 
451
488
                        BucketInfo bucketFound = bucketList.get(0);
452
489
                        BucketLogData logData = bucketFound.getLoggingEnabled() ? request
453
490
                                        .getLogData() : null;
454
 
                                        if (bucketFound.canWrite(userId)) {
 
491
                                        if (ctx.hasAdministrativePrivileges() || (
 
492
                                                        Lookups.checkPrivilege(PolicySpec.S3_DELETEBUCKET,
 
493
                                                                        PolicySpec.VENDOR_S3,
 
494
                                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
495
                                                                        bucketName,
 
496
                                                                        bucketFound.getOwnerId()))) {
455
497
                                                EntityWrapper<ObjectInfo> dbObject = db
456
 
                                                .recast(ObjectInfo.class);
 
498
                                                                .recast(ObjectInfo.class);
457
499
                                                ObjectInfo searchObject = new ObjectInfo();
458
500
                                                searchObject.setBucketName(bucketName);
459
501
                                                searchObject.setDeleted(false);
461
503
                                                if (objectInfos.size() == 0) {
462
504
                                                        //check if the bucket contains any images
463
505
                                                        EntityWrapper<ImageCacheInfo> dbIC = db
464
 
                                                        .recast(ImageCacheInfo.class);
 
506
                                                                        .recast(ImageCacheInfo.class);
465
507
                                                        ImageCacheInfo searchImageCacheInfo = new ImageCacheInfo();
466
508
                                                        searchImageCacheInfo.setBucketName(bucketName);
467
509
                                                        List<ImageCacheInfo> foundImageCacheInfos = dbIC
468
 
                                                        .query(searchImageCacheInfo);
 
510
                                                                        .query(searchImageCacheInfo);
469
511
 
470
512
                                                        if (foundImageCacheInfos.size() > 0) {
471
513
                                                                db.rollback();
489
531
                                                                // set exception code in reply
490
532
                                                                LOG.error(ex);
491
533
                                                        }
492
 
 
493
 
                                                        if (WalrusProperties.enableVirtualHosting) {
494
 
                                                                URI walrusUri;
495
 
                                                                String address;
496
 
                                                                RemoveARecordType removeARecordType = new RemoveARecordType();
497
 
                                                                removeARecordType.setUserId(userId);
498
 
                                                                String zone = WalrusProperties.WALRUS_SUBDOMAIN + ".";
499
 
                                                                removeARecordType.setName(bucketName + "." + zone);
500
 
                                                                removeARecordType.setZone(zone);
501
 
                                                                try {
502
 
                                                                        walrusUri = new URI(SystemConfiguration.getWalrusUrl());
503
 
                                                                        address = walrusUri.getHost();
504
 
                                                                } catch (URISyntaxException e) {
505
 
                                                                        db.rollback();
506
 
                                                                        throw new EucalyptusCloudException("Could not get Walrus URL");
507
 
                                                                }
508
 
                                                                removeARecordType.setAddress(address);
509
 
                                                                try {
510
 
                                                                        ServiceDispatcher.lookupSingle(Component.dns).send(
511
 
                                                                                        removeARecordType);
512
 
                                                                        LOG.info("Removing mapping for "
513
 
                                                                                        + removeARecordType.getName());
514
 
                                                                } catch (Exception ex) {
515
 
                                                                        LOG.error("Could not update DNS record", ex);
516
 
                                                                }
517
 
                                                        }
518
 
 
 
534
                                                        QueueSender queueSender = QueueFactory.getInstance().getSender(QueueIdentifier.S3);
 
535
                                                        queueSender.send(new S3Event(false, ctx.getUser().getUserId(),
 
536
                                                                ctx.getUser().getName(), ctx.getAccount().getAccountNumber(),
 
537
                                                                ctx.getAccount().getName()));
519
538
                                                        Status status = new Status();
520
539
                                                        status.setCode(204);
521
540
                                                        status.setDescription("No Content");
542
561
 
543
562
        public GetBucketAccessControlPolicyResponseType getBucketAccessControlPolicy(
544
563
                        GetBucketAccessControlPolicyType request)
545
 
        throws EucalyptusCloudException {
 
564
                                        throws EucalyptusCloudException {
546
565
                GetBucketAccessControlPolicyResponseType reply = (GetBucketAccessControlPolicyResponseType) request
547
 
                .getReply();
 
566
                                .getReply();
548
567
 
549
568
                String bucketName = request.getBucket();
550
 
                String userId = request.getUserId();
 
569
                Context ctx = Contexts.lookup();
 
570
                Account account = ctx.getAccount();
551
571
                String ownerId = null;
552
572
 
553
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
573
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
554
574
                BucketInfo bucketInfo = new BucketInfo(bucketName);
555
575
                List<BucketInfo> bucketList = db.query(bucketInfo);
556
576
 
562
582
                        BucketInfo bucket = bucketList.get(0);
563
583
                        logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
564
584
                        List<GrantInfo> grantInfos = bucket.getGrants();
565
 
                        if (bucket.canReadACP(userId)) {
 
585
                        if (ctx.hasAdministrativePrivileges() || (
 
586
                                        bucket.canReadACP(account.getAccountNumber()) &&
 
587
                                        (bucket.isGlobalReadACP() || Lookups.checkPrivilege(PolicySpec.S3_GETBUCKETACL,
 
588
                                                        PolicySpec.VENDOR_S3,
 
589
                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
590
                                                        bucketName,
 
591
                                                        null)))) {
566
592
                                if (logData != null) {
567
593
                                        updateLogData(bucket, logData);
568
594
                                        reply.setLogData(logData);
574
600
                                        String uId = grantInfo.getUserId();
575
601
                                        try {
576
602
                                                if (uId != null) {
577
 
                                                        User grantUserInfo = Users.lookupUser(uId);
578
 
                                                        addPermission(grants, grantUserInfo, grantInfo);
 
603
                                                        addPermission(grants, Accounts.lookupAccountById(uId), grantInfo);
579
604
                                                } else {
580
605
                                                        addPermission(grants, grantInfo);
581
606
                                                }
582
 
                                        } catch (NoSuchUserException e) {
 
607
                                        } catch (AuthException e) {
583
608
                                                db.rollback();
584
609
                                                throw new AccessDeniedException("Bucket", bucketName,
585
610
                                                                logData);
586
611
                                        }
587
612
                                }
588
613
                                accessControlList.setGrants(grants);
 
614
                        } else {
 
615
                                LOG.error( "Not authorized to get bucket ACL by " + ctx.getUserFullName( ) );
 
616
                                db.rollback();
 
617
                                throw new AccessDeniedException("Bucket", bucketName, logData);
589
618
                        }
590
619
                } else {
591
620
                        db.rollback();
594
623
 
595
624
                AccessControlPolicyType accessControlPolicy = new AccessControlPolicyType();
596
625
                try {
597
 
                        User ownerUserInfo = Users.lookupUser(ownerId);
598
 
                        accessControlPolicy.setOwner(new CanonicalUserType(ownerUserInfo
599
 
                                        .getQueryId(), ownerUserInfo.getName()));
 
626
                        Account ownerInfo = Accounts.lookupAccountById(ownerId);
 
627
                        accessControlPolicy.setOwner(new CanonicalUserType(ownerInfo.getName(), ownerInfo.getAccountNumber()));
600
628
                        accessControlPolicy.setAccessControlList(accessControlList);
601
 
                } catch (NoSuchUserException e) {
 
629
                } catch (AuthException e) {
602
630
                        db.rollback();
603
631
                        throw new AccessDeniedException("Bucket", bucketName, logData);
604
632
                }
607
635
                return reply;
608
636
        }
609
637
 
610
 
        private static void addPermission(ArrayList<Grant> grants, User userInfo,
611
 
                        GrantInfo grantInfo) {
612
 
                CanonicalUserType user = new CanonicalUserType(userInfo.getQueryId(),
613
 
                                userInfo.getName());
 
638
        private static void addPermission(ArrayList<Grant> grants, Account account,
 
639
                        GrantInfo grantInfo) throws AuthException {
 
640
                CanonicalUserType user = new CanonicalUserType(account.getName(), account.getAccountNumber());
614
641
 
615
642
                if (grantInfo.canRead() && grantInfo.canWrite()
616
643
                                && grantInfo.canReadACP() && grantInfo.isWriteACP()) {
665
692
        }
666
693
 
667
694
        public PutObjectResponseType putObject(PutObjectType request)
668
 
        throws EucalyptusCloudException {
 
695
                        throws EucalyptusCloudException {
669
696
                PutObjectResponseType reply = (PutObjectResponseType) request
670
 
                .getReply();
671
 
                String userId = request.getUserId();
 
697
                                .getReply();
 
698
                Context ctx = Contexts.lookup();
 
699
                Account account = ctx.getAccount() ;
672
700
 
673
701
                String bucketName = request.getBucket();
674
702
                String objectKey = request.getKey();
679
707
                Date lastModified = null;
680
708
 
681
709
                AccessControlListType accessControlList = request
682
 
                .getAccessControlList();
 
710
                                .getAccessControlList();
683
711
                if (accessControlList == null) {
684
712
                        accessControlList = new AccessControlListType();
685
713
                }
688
716
                String randomKey = request.getRandomKey();
689
717
                WalrusDataMessenger messenger = WalrusRESTBinding.getWriteMessenger();
690
718
 
691
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
719
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
692
720
                BucketInfo bucketInfo = new BucketInfo(bucketName);
693
721
                List<BucketInfo> bucketList = db.query(bucketInfo);
694
722
 
695
723
                if (bucketList.size() > 0) {
696
724
                        BucketInfo bucket = bucketList.get(0);
697
 
                        BucketLogData logData = bucket.getLoggingEnabled() ? request
698
 
                                        .getLogData() : null;
699
 
                                        if (bucket.canWrite(userId)) {
700
 
                                                if (logData != null)
701
 
                                                        reply.setLogData(logData);
702
 
                                                String objectName;
703
 
                                                String versionId;
704
 
                                                ObjectInfo objectInfo = null;
705
 
                                                if (bucket.isVersioningEnabled()) {
706
 
                                                        objectInfo = new ObjectInfo(bucketName, objectKey);
707
 
                                                        objectInfo.setOwnerId(userId);
708
 
                                                        List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
709
 
                                                        objectInfo.addGrants(userId, grantInfos, accessControlList);
710
 
                                                        objectInfo.setGrants(grantInfos);
711
 
                                                        objectName = UUID.randomUUID().toString();
712
 
                                                        objectInfo.setObjectName(objectName);
713
 
                                                        objectInfo.setSize(0L);
714
 
                                                        versionId = UUID.randomUUID().toString().replaceAll("-", "");
715
 
                                                } else {
716
 
                                                        versionId = WalrusProperties.NULL_VERSION_ID;
 
725
                        BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
 
726
                        long objSize = 0;
 
727
                        try {
 
728
                                objSize = Long.valueOf( request.getContentLength( ) );
 
729
                        } catch ( NumberFormatException e ) {
 
730
                                LOG.error( "Invalid content length " + request.getContentLength( ) );
 
731
                                // TODO(wenye): should handle this properly.
 
732
                                objSize = 1L;
 
733
                        }
 
734
                        if (ctx.hasAdministrativePrivileges() || (
 
735
                                        bucket.canWrite(account.getAccountNumber()) &&
 
736
                                        (bucket.isGlobalWrite() || Lookups.checkPrivilege(PolicySpec.S3_PUTOBJECT,
 
737
                                                        PolicySpec.VENDOR_S3,
 
738
                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
739
                                                        bucketName,
 
740
                                                        null)))) {
 
741
                                if (logData != null)
 
742
                                        reply.setLogData(logData);
 
743
                                String objectName;
 
744
                                String versionId;
 
745
                                ObjectInfo objectInfo = null;
 
746
                                if (bucket.isVersioningEnabled()) {
 
747
                                        objectInfo = new ObjectInfo(bucketName, objectKey);
 
748
                                        objectInfo.setOwnerId(account.getAccountNumber());
 
749
                                        List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
 
750
                                        objectInfo.addGrants(account.getAccountNumber(), grantInfos, accessControlList);
 
751
                                        objectInfo.setGrants(grantInfos);
 
752
                                        objectName = UUID.randomUUID().toString();
 
753
                                        objectInfo.setObjectName(objectName);
 
754
                                        objectInfo.setSize(0L);
 
755
                                        versionId = UUID.randomUUID().toString().replaceAll("-", "");
 
756
                                } else {
 
757
                                        versionId = WalrusProperties.NULL_VERSION_ID;
 
758
                                        ObjectInfo searchObject = new ObjectInfo(bucketName, objectKey);
 
759
                                        searchObject.setVersionId(versionId);                                                   
 
760
                                        EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
 
761
                                        try {
 
762
                                                ObjectInfo foundObject = dbObject.getUnique(searchObject);
 
763
                                                if (!foundObject.canWrite(account.getAccountNumber())) {
 
764
                                                        db.rollback();
 
765
                                                        messenger.removeQueue(key, randomKey);
 
766
                                                        throw new AccessDeniedException("Key", objectKey,
 
767
                                                                        logData);
 
768
                                                } 
 
769
                                                objectName = foundObject.getObjectName();
 
770
                                        } catch(AccessDeniedException ex) { 
 
771
                                                throw ex;
 
772
                                        } catch(EucalyptusCloudException ex) {
 
773
                                                objectInfo = new ObjectInfo(bucketName, objectKey);
 
774
                                                objectInfo.setOwnerId(account.getAccountNumber());
 
775
                                                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
 
776
                                                objectInfo.addGrants(account.getAccountNumber(), grantInfos, accessControlList);
 
777
                                                objectInfo.setGrants(grantInfos);
 
778
                                                objectName =  UUID.randomUUID().toString();
 
779
                                                objectInfo.setObjectName(objectName);
 
780
                                                objectInfo.setSize(0L);
 
781
                                        }
 
782
                                }
 
783
                                if (bucket.isVersioningEnabled()) {
 
784
                                        reply.setVersionId(versionId);
 
785
                                }
 
786
                                db.commit();
 
787
                                // writes are unconditional
 
788
                                WalrusDataQueue<WalrusDataMessage> putQueue = messenger
 
789
                                                .getQueue(key, randomKey);
 
790
 
 
791
                                try {
 
792
                                        WalrusDataMessage dataMessage;
 
793
                                        String tempObjectName = objectName;
 
794
                                        MessageDigest digest = null;
 
795
                                        long size = 0;
 
796
                                        FileIO fileIO = null;
 
797
                                        while ((dataMessage = putQueue.take()) != null) {
 
798
                                                if(putQueue.getInterrupted()) {                                         
 
799
                                                        if(WalrusDataMessage.isEOF(dataMessage)) {
 
800
                                                                WalrusMonitor monitor = messenger.getMonitor(key);
 
801
                                                                if(monitor.getLastModified() == null) {
 
802
                                                                        LOG.trace("Monitor wait: " + key + " random: " + randomKey);
 
803
                                                                        synchronized (monitor) {
 
804
                                                                                monitor.wait();
 
805
                                                                        }
 
806
                                                                }
 
807
                                                                LOG.trace("Monitor resume: " + key + " random: " + randomKey);
 
808
                                                                lastModified = monitor.getLastModified();
 
809
                                                                md5 = monitor.getMd5();
 
810
                                                                //ok we are done here
 
811
                                                                if(fileIO != null)
 
812
                                                                        fileIO.finish();
 
813
                                                                ObjectDeleter objectDeleter = new ObjectDeleter(bucketName,
 
814
                                                                                tempObjectName,
 
815
                                                                                -1L,
 
816
                                                                                ctx.getUser().getName(),
 
817
                                                                                ctx.getUser().getUserId(),
 
818
                                                                                ctx.getAccount().getName(),
 
819
                                                                                ctx.getAccount().getAccountNumber());
 
820
                                                                Threads.lookup(Walrus.class, WalrusManager.ObjectDeleter.class).limitTo(10).submit(objectDeleter);
 
821
                                                                LOG.info("Transfer interrupted: "+ key);
 
822
                                                                messenger.removeQueue(key, randomKey);
 
823
                                                                break;  
 
824
                                                        }
 
825
                                                        continue;
 
826
                                                }
 
827
                                                if (WalrusDataMessage.isStart(dataMessage)) {
 
828
                                                        tempObjectName = UUID.randomUUID().toString();
 
829
                                                        digest = Digest.MD5.get();
 
830
                                                        try {
 
831
                                                                fileIO = storageManager.prepareForWrite(
 
832
                                                                                bucketName, tempObjectName);
 
833
                                                        } catch (Exception ex) {
 
834
                                                                messenger.removeQueue(key, randomKey);
 
835
                                                                throw new EucalyptusCloudException(ex);
 
836
                                                        }
 
837
                                                } else if (WalrusDataMessage.isEOF(dataMessage)) {
 
838
                                                        if (digest != null) {
 
839
                                                                md5 = Hashes.bytesToHex(digest.digest());
 
840
                                                        } else {
 
841
                                                                WalrusMonitor monitor = messenger.getMonitor(key);
 
842
                                                                md5 = monitor.getMd5();
 
843
                                                                lastModified = monitor.getLastModified();
 
844
                                                                if (md5 == null) {
 
845
                                                                        LOG.error("ETag did not match for: " + randomKey + " Computed MD5 is null");
 
846
                                                                        throw new ContentMismatchException(bucketName + "/" + objectKey);
 
847
                                                                }
 
848
                                                                break;
 
849
                                                        }
 
850
                                                        String contentMD5 = request.getContentMD5();
 
851
                                                        if (contentMD5 != null) {
 
852
                                                                String contentMD5AsHex = Hashes.bytesToHex(Base64.decode(contentMD5));
 
853
                                                                if(!contentMD5AsHex.equals(md5)) {
 
854
                                                                        if(fileIO != null)
 
855
                                                                                fileIO.finish();
 
856
                                                                        ObjectDeleter objectDeleter = new ObjectDeleter(bucketName,
 
857
                                                                                        tempObjectName,
 
858
                                                                                        -1L,
 
859
                                                                                        ctx.getUser().getName(),
 
860
                                                                                        ctx.getUser().getUserId(),
 
861
                                                                                        ctx.getAccount().getName(),
 
862
                                                                                        ctx.getAccount().getAccountNumber());
 
863
                                                                        Threads.lookup(Walrus.class, WalrusManager.ObjectDeleter.class).limitTo(10).submit(objectDeleter);
 
864
                                                                        messenger.removeQueue(key, randomKey);
 
865
                                                                        LOG.error("ETag did not match for: " + randomKey + " Expected: " + contentMD5AsHex + " Computed: " + md5);
 
866
                                                                        throw new ContentMismatchException(bucketName + "/" + objectKey);
 
867
                                                                }
 
868
                                                        }
 
869
                                                        // commit object
 
870
                                                        try {
 
871
                                                                if (fileIO != null)
 
872
                                                                        fileIO.finish();
 
873
                                                                storageManager.renameObject(bucketName,
 
874
                                                                                tempObjectName, objectName);
 
875
                                                        } catch (IOException ex) {
 
876
                                                                LOG.error(ex);
 
877
                                                                messenger.removeQueue(key, randomKey);
 
878
                                                                throw new EucalyptusCloudException(objectKey);
 
879
                                                        }
 
880
                                                        lastModified = new Date();
717
881
                                                        ObjectInfo searchObject = new ObjectInfo(bucketName, objectKey);
718
 
                                                        searchObject.setVersionId(versionId);                                                   
719
 
                                                        EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
 
882
                                                        searchObject.setVersionId(versionId);
 
883
                                                        EntityWrapper<ObjectInfo> dbObject = EntityWrapper.get(ObjectInfo.class);
 
884
                                                        ObjectInfo foundObject;
720
885
                                                        try {
721
 
                                                                ObjectInfo foundObject = dbObject.getUnique(searchObject);
722
 
                                                                if (!foundObject.canWrite(userId)) {
723
 
                                                                        db.rollback();
724
 
                                                                        messenger.removeQueue(key, randomKey);
725
 
                                                                        throw new AccessDeniedException("Key", objectKey,
726
 
                                                                                        logData);
727
 
                                                                } 
728
 
                                                                objectName = foundObject.getObjectName();
729
 
                                                        } catch(AccessDeniedException ex) { 
730
 
                                                                throw ex;
731
 
                                                        } catch(EucalyptusCloudException ex) {
732
 
                                                                objectInfo = new ObjectInfo(bucketName, objectKey);
733
 
                                                                objectInfo.setOwnerId(userId);
734
 
                                                                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
735
 
                                                                objectInfo.addGrants(userId, grantInfos, accessControlList);
736
 
                                                                objectInfo.setGrants(grantInfos);
737
 
                                                                objectName =  UUID.randomUUID().toString();
738
 
                                                                objectInfo.setObjectName(objectName);
739
 
                                                                objectInfo.setSize(0L);
740
 
                                                        }
741
 
                                                }
742
 
 
743
 
                                                db.commit();
744
 
                                                // writes are unconditional
745
 
                                                WalrusDataQueue<WalrusDataMessage> putQueue = messenger
746
 
                                                .getQueue(key, randomKey);
747
 
 
748
 
                                                try {
749
 
                                                        WalrusDataMessage dataMessage;
750
 
                                                        String tempObjectName = objectName;
751
 
                                                        MessageDigest digest = null;
752
 
                                                        long size = 0;
753
 
                                                        FileIO fileIO = null;
754
 
                                                        while ((dataMessage = putQueue.take()) != null) {
755
 
                                                                if(putQueue.getInterrupted()) {                                         
756
 
                                                                        if(WalrusDataMessage.isEOF(dataMessage)) {
757
 
                                                                                WalrusMonitor monitor = messenger.getMonitor(key);
758
 
                                                                                if(monitor.getLastModified() == null) {
759
 
                                                                                        synchronized (monitor) {
760
 
                                                                                                monitor.wait();
761
 
                                                                                        }
762
 
                                                                                }
763
 
                                                                                lastModified = monitor.getLastModified();
764
 
                                                                                md5 = monitor.getMd5();
765
 
                                                                                //ok we are done here
766
 
                                                                                if(fileIO != null)
767
 
                                                                                        fileIO.finish();
768
 
                                                                                ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, tempObjectName, -1L);
769
 
                                                                                objectDeleter.start();
770
 
                                                                                LOG.info("Transfer interrupted: "+ key);
771
 
                                                                                messenger.removeQueue(key, randomKey);
772
 
                                                                                break;  
773
 
                                                                        }
774
 
                                                                        continue;
 
886
                                                                foundObject = dbObject.getUnique(searchObject);
 
887
                                                                if (ctx.hasAdministrativePrivileges() || foundObject.canWriteACP(account.getAccountNumber())) {
 
888
                                                                        List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
 
889
                                                                        foundObject.addGrants(account.getAccountNumber(), grantInfos,
 
890
                                                                                        accessControlList);
 
891
                                                                        foundObject.setGrants(grantInfos);
775
892
                                                                }
776
 
                                                                if (WalrusDataMessage.isStart(dataMessage)) {
777
 
                                                                        tempObjectName = UUID.randomUUID().toString();
778
 
                                                                        digest = Digest.MD5.get();
779
 
                                                                        try {
780
 
                                                                                fileIO = storageManager.prepareForWrite(
781
 
                                                                                                bucketName, tempObjectName);
782
 
                                                                        } catch (Exception ex) {
783
 
                                                                                messenger.removeQueue(key, randomKey);
784
 
                                                                                throw new EucalyptusCloudException(ex);
785
 
                                                                        }
786
 
                                                                } else if (WalrusDataMessage.isEOF(dataMessage)) {
787
 
                                                                        // commit object
788
 
                                                                        try {
789
 
                                                                                if (fileIO != null)
790
 
                                                                                        fileIO.finish();
791
 
                                                                                storageManager.renameObject(bucketName,
792
 
                                                                                                tempObjectName, objectName);
793
 
                                                                        } catch (IOException ex) {
794
 
                                                                                LOG.error(ex);
795
 
                                                                                messenger.removeQueue(key, randomKey);
796
 
                                                                                throw new EucalyptusCloudException(objectKey);
797
 
                                                                        }
798
 
                                                                        if (digest != null)
799
 
                                                                                md5 = Hashes.bytesToHex(digest.digest());
800
 
                                                                        lastModified = new Date();
801
 
                                                                        ObjectInfo searchObject = new ObjectInfo(bucketName, objectKey);
802
 
                                                                        searchObject.setVersionId(versionId);
803
 
                                                                        EntityWrapper<ObjectInfo> dbObject = WalrusControl.getEntityWrapper();
804
 
                                                                        List<ObjectInfo> objectInfos = dbObject.query(new ObjectInfo(bucketName, objectKey));
805
 
                                                                        for(ObjectInfo objInfo : objectInfos) {
806
 
                                                                                objInfo.setLast(false);
807
 
                                                                        }
808
 
                                                                        ObjectInfo foundObject;
809
 
                                                                        try {
810
 
                                                                                foundObject = dbObject.getUnique(searchObject);
811
 
                                                                                if (foundObject.canWriteACP(userId)) {
812
 
                                                                                        List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
813
 
                                                                                        foundObject.addGrants(userId, grantInfos,
814
 
                                                                                                        accessControlList);
815
 
                                                                                        foundObject.setGrants(grantInfos);
816
 
                                                                                }
817
 
                                                                                if (WalrusProperties.enableTorrents) {
818
 
                                                                                        EntityWrapper<TorrentInfo> dbTorrent = dbObject
 
893
                                                                if (WalrusProperties.enableTorrents) {
 
894
                                                                        EntityWrapper<TorrentInfo> dbTorrent = dbObject
819
895
                                                                                        .recast(TorrentInfo.class);
820
 
                                                                                        TorrentInfo torrentInfo = new TorrentInfo(bucketName,
821
 
                                                                                                        objectKey);
822
 
                                                                                        List<TorrentInfo> torrentInfos = dbTorrent
 
896
                                                                        TorrentInfo torrentInfo = new TorrentInfo(bucketName,
 
897
                                                                                        objectKey);
 
898
                                                                        List<TorrentInfo> torrentInfos = dbTorrent
823
899
                                                                                        .query(torrentInfo);
824
 
                                                                                        if (torrentInfos.size() > 0) {
825
 
                                                                                                TorrentInfo foundTorrentInfo = torrentInfos.get(0);
826
 
                                                                                                TorrentClient torrentClient = Torrents
 
900
                                                                        if (torrentInfos.size() > 0) {
 
901
                                                                                TorrentInfo foundTorrentInfo = torrentInfos.get(0);
 
902
                                                                                TorrentClient torrentClient = Torrents
827
903
                                                                                                .getClient(bucketName + objectKey);
828
 
                                                                                                if (torrentClient != null) {
829
 
                                                                                                        torrentClient.bye();
830
 
                                                                                                }
831
 
                                                                                                dbTorrent.delete(foundTorrentInfo);
832
 
                                                                                        }
833
 
                                                                                } else {
834
 
                                                                                        LOG
835
 
                                                                                        .warn("Bittorrent support has been disabled. Please check pre-requisites");
836
 
                                                                                }
837
 
                                                                        } catch (EucalyptusCloudException ex) {
838
 
                                                                                if(objectInfo != null) {
839
 
                                                                                        foundObject = objectInfo;
840
 
                                                                                } else {
841
 
                                                                                        db.rollback();
842
 
                                                                                        throw new EucalyptusCloudException("Unable to update object: " + bucketName + "/" + objectKey);
843
 
                                                                                }
844
 
                                                                        }
845
 
                                                                        foundObject.setVersionId(versionId);
846
 
                                                                        foundObject.replaceMetaData(request.getMetaData());
847
 
                                                                        foundObject.setEtag(md5);
848
 
                                                                        foundObject.setSize(size);
849
 
                                                                        foundObject.setLastModified(lastModified);
850
 
                                                                        foundObject.setStorageClass("STANDARD");
851
 
                                                                        foundObject.setContentType(request
852
 
                                                                                        .getContentType());
853
 
                                                                        foundObject.setContentDisposition(request
854
 
                                                                                        .getContentDisposition());
855
 
                                                                        foundObject.setLast(true);
856
 
                                                                        foundObject.setDeleted(false);
857
 
                                                                        reply.setSize(size);
858
 
                                                                        ObjectInfo deleteMarker = new ObjectInfo(bucketName, objectKey);
859
 
                                                                        deleteMarker.setDeleted(true);
860
 
                                                                        try {
861
 
                                                                                ObjectInfo foundDeleteMarker = dbObject.getUnique(deleteMarker);
862
 
                                                                                dbObject.delete(foundDeleteMarker);
863
 
                                                                        } catch(EucalyptusCloudException ex) {
864
 
                                                                                //no delete marker found.
865
 
                                                                                LOG.trace("No delete marker found for: " + bucketName + "/" + objectKey);
866
 
                                                                        }
867
 
                                                                        if (bucket.isVersioningEnabled()) {
868
 
                                                                                reply.setVersionId(versionId);
869
 
                                                                        }
870
 
                                                                        EntityWrapper<BucketInfo> dbBucket = dbObject.recast(BucketInfo.class);                                                                         
871
 
                                                                        try {
872
 
                                                                                bucket = dbBucket.getUnique(new BucketInfo(bucketName));
873
 
                                                                        } catch(EucalyptusCloudException e) {
874
 
                                                                                LOG.error(e);
875
 
                                                                                dbObject.rollback();
876
 
                                                                                throw new NoSuchBucketException(bucketName);
877
 
                                                                        }
878
 
                                                                        Long bucketSize = bucket.getBucketSize();
879
 
                                                                        long newSize = bucketSize + oldBucketSize
880
 
                                                                        + size;
881
 
                                                                        if (WalrusProperties.shouldEnforceUsageLimits
882
 
                                                                                        && !request.isAdministrator()) {
883
 
                                                                                if (newSize > (WalrusInfo.getWalrusInfo().getStorageMaxBucketSizeInMB() * WalrusProperties.M)) {
884
 
                                                                                        messenger.removeQueue(key, randomKey);
885
 
                                                                                        dbObject.rollback();
886
 
                                                                                        throw new EntityTooLargeException(
887
 
                                                                                                        "Key", objectKey);
888
 
                                                                                }
889
 
                                                                        }
890
 
                                                                        bucket.setBucketSize(newSize);
891
 
                                                                        if (WalrusProperties.trackUsageStatistics) {
892
 
                                                                                walrusStatistics.updateBytesIn(size);
893
 
                                                                                walrusStatistics.updateSpaceUsed(size);
894
 
                                                                        }
895
 
                                                                        if (logData != null) {
896
 
                                                                                logData.setObjectSize(size);
897
 
                                                                                updateLogData(bucket, logData);
898
 
                                                                        }
899
 
                                                                        if(objectInfo != null)
900
 
                                                                                dbObject.add(foundObject);
901
 
                                                                        dbObject.commit();
902
 
                                                                        if (logData != null) {
903
 
                                                                                logData.setTurnAroundTime(Long
904
 
                                                                                                .parseLong(new String(dataMessage
905
 
                                                                                                                .getPayload())));
906
 
                                                                        }
907
 
                                                                        // restart all interrupted puts
908
 
                                                                        WalrusMonitor monitor = messenger.getMonitor(key);
909
 
                                                                        synchronized (monitor) {
910
 
                                                                                monitor.setLastModified(lastModified);
911
 
                                                                                monitor.setMd5(md5);
912
 
                                                                                monitor.notifyAll();
913
 
                                                                        }
914
 
                                                                        messenger.removeMonitor(key);
 
904
                                                                                if (torrentClient != null) {
 
905
                                                                                        torrentClient.bye();
 
906
                                                                                }
 
907
                                                                                dbTorrent.delete(foundTorrentInfo);
 
908
                                                                        }
 
909
                                                                } else {
 
910
                                                                        LOG
 
911
                                                                        .warn("Bittorrent support has been disabled. Please check pre-requisites");
 
912
                                                                }
 
913
                                                        } catch (EucalyptusCloudException ex) {
 
914
                                                                if(objectInfo != null) {
 
915
                                                                        foundObject = objectInfo;
 
916
                                                                } else {
 
917
                                                                        dbObject.rollback();
 
918
                                                                        throw new EucalyptusCloudException("Unable to update object: " + bucketName + "/" + objectKey);
 
919
                                                                }
 
920
                                                        }
 
921
                                                        foundObject.setVersionId(versionId);
 
922
                                                        foundObject.replaceMetaData(request.getMetaData());
 
923
                                                        foundObject.setEtag(md5);
 
924
                                                        foundObject.setSize(size);
 
925
                                                        foundObject.setLastModified(lastModified);
 
926
                                                        foundObject.setStorageClass("STANDARD");
 
927
                                                        foundObject.setContentType(request
 
928
                                                                        .getContentType());
 
929
                                                        foundObject.setContentDisposition(request
 
930
                                                                        .getContentDisposition());
 
931
                                                        foundObject.setLast(true);
 
932
                                                        foundObject.setDeleted(false);
 
933
                                                        reply.setSize(size);
 
934
                                                        if (!ctx.hasAdministrativePrivileges() &&
 
935
                                                                        !Permissions.canAllocate(PolicySpec.VENDOR_S3,
 
936
                                                                                        PolicySpec.S3_RESOURCE_OBJECT,
 
937
                                                                                        bucketName,
 
938
                                                                                        PolicySpec.S3_PUTOBJECT,
 
939
                                                                                        ctx.getUser(),
 
940
                                                                                        oldBucketSize + size)) {
 
941
                                                                dbObject.rollback();
 
942
                                                                LOG.error("Quota exceeded for Walrus putObject");
 
943
                                                                throw new EntityTooLargeException("Key", objectKey);
 
944
                                                        }                                                       
 
945
                                                        boolean success = false;
 
946
                                                        int retryCount = 0;
 
947
                                                        do {
 
948
                                                                try {
 
949
                                                                        incrementBucketSize(bucketName, objectKey, oldBucketSize, size);
 
950
                                                                        success = true;
 
951
                                                                } catch (EntityTooLargeException ex) {
915
952
                                                                        messenger.removeQueue(key, randomKey);
916
 
                                                                        LOG.info("Transfer complete: " + key);
917
 
                                                                        break;
918
 
                                                                } else {
919
 
                                                                        assert (WalrusDataMessage.isData(dataMessage));
920
 
                                                                        byte[] data = dataMessage.getPayload();
921
 
                                                                        // start writing object (but do not commit yet)
922
 
                                                                        try {
923
 
                                                                                if (fileIO != null)
924
 
                                                                                        fileIO.write(data);
925
 
                                                                        } catch (IOException ex) {
926
 
                                                                                LOG.error(ex);
 
953
                                                                        dbObject.rollback();
 
954
                                                                        throw ex;
 
955
                                                                } catch (NoSuchBucketException ex) {
 
956
                                                                        dbObject.rollback();
 
957
                                                                        throw ex;
 
958
                                                                } catch (RollbackException ex) {
 
959
                                                                        retryCount++;
 
960
                                                                        LOG.trace("retrying update: " + bucketName);
 
961
                                                                } catch (EucalyptusCloudException ex) {
 
962
                                                                        dbObject.rollback();
 
963
                                                                        throw ex;
 
964
                                                                }
 
965
                                                        } while(!success && (retryCount < 5));
 
966
                                                        if (WalrusProperties.trackUsageStatistics) {
 
967
                                                                walrusStatistics.updateBytesIn(size);
 
968
                                                                walrusStatistics.updateSpaceUsed(size);
 
969
                                                        }
 
970
                                                        if (logData != null) {
 
971
                                                                logData.setObjectSize(size);
 
972
                                                                updateLogData(bucket, logData);
 
973
                                                        }
 
974
                                                        if(objectInfo != null) {
 
975
                                                                dbObject.add(foundObject);
 
976
                                                        } 
 
977
                                                        success = false;
 
978
                                                        try {
 
979
                                                                dbObject.commit();
 
980
                                                                success = true;
 
981
                                                        } catch (RollbackException ex) {
 
982
                                                                dbObject.rollback();
 
983
                                                                LOG.error(ex, ex);
 
984
                                                        }
 
985
 
 
986
                                                        dbObject = EntityWrapper.get(ObjectInfo.class);
 
987
                                                        List<ObjectInfo> objectInfos = dbObject.query(new ObjectInfo(bucketName, objectKey));
 
988
                                                        for(ObjectInfo objInfo : objectInfos) {
 
989
                                                                if (!success) {
 
990
                                                                        if (objInfo.getLast()) {
 
991
                                                                                lastModified = objInfo.getLastModified();
 
992
                                                                                md5 = objInfo.getEtag();
927
993
                                                                        }
928
 
                                                                        // calculate md5 on the fly
929
 
                                                                        size += data.length;
930
 
                                                                        if (digest != null)
931
 
                                                                                digest.update(data);
932
 
                                                                }
933
 
                                                        }
934
 
                                                } catch (InterruptedException ex) {
935
 
                                                        LOG.error(ex, ex);
 
994
                                                                        success = true;
 
995
                                                                }
 
996
                                                                if (!versionId.equals(objInfo.getVersionId())) {
 
997
                                                                        objInfo.setLast(false);
 
998
                                                                }
 
999
                                                        }
 
1000
                                                        dbObject.commit();
 
1001
 
 
1002
                                                        dbObject = EntityWrapper.get(ObjectInfo.class);
 
1003
                                                        ObjectInfo deleteMarker = new ObjectInfo(bucketName, objectKey);
 
1004
                                                        deleteMarker.setDeleted(true);
 
1005
                                                        try {
 
1006
                                                                ObjectInfo foundDeleteMarker = dbObject.getUnique(deleteMarker);
 
1007
                                                                dbObject.delete(foundDeleteMarker);
 
1008
                                                        } catch(EucalyptusCloudException ex) {
 
1009
                                                                //no delete marker found.
 
1010
                                                                LOG.trace("No delete marker found for: " + bucketName + "/" + objectKey);
 
1011
                                                        }
 
1012
                                                        dbObject.commit();
 
1013
 
 
1014
                                                        if (logData != null) {
 
1015
                                                                logData.setTurnAroundTime(Long
 
1016
                                                                                .parseLong(new String(dataMessage
 
1017
                                                                                                .getPayload())));
 
1018
                                                        }
 
1019
                                                        // restart all interrupted puts
 
1020
                                                        WalrusMonitor monitor = messenger.getMonitor(key);
 
1021
                                                        synchronized (monitor) {
 
1022
                                                                monitor.setLastModified(lastModified);
 
1023
                                                                monitor.setMd5(md5);
 
1024
                                                                monitor.notifyAll();
 
1025
                                                        }
 
1026
                                                        //messenger.removeMonitor(key);
 
1027
                                                        messenger.clearQueues(key);
936
1028
                                                        messenger.removeQueue(key, randomKey);
937
 
                                                        throw new EucalyptusCloudException("Transfer interrupted: "
938
 
                                                                        + key + "." + randomKey);
 
1029
                                                        LOG.info("Transfer complete: " + key);
 
1030
                                                        QueueSender queueSender =
 
1031
                                                                        QueueFactory.getInstance()
 
1032
                                                                        .getSender(QueueIdentifier.S3);
 
1033
                                                        queueSender.send(new S3Event(true,
 
1034
                                                                        size / WalrusProperties.M,
 
1035
                                                                        ctx.getUser().getUserId(),
 
1036
                                                                        ctx.getUser().getName(),
 
1037
                                                                        ctx.getAccount().getAccountNumber(),
 
1038
                                                                        ctx.getAccount().getName()));
 
1039
                                                        break;
 
1040
                                                } else {
 
1041
                                                        assert (WalrusDataMessage.isData(dataMessage));
 
1042
                                                        byte[] data = dataMessage.getPayload();
 
1043
                                                        // start writing object (but do not commit yet)
 
1044
                                                        try {
 
1045
                                                                if (fileIO != null)
 
1046
                                                                        fileIO.write(data);
 
1047
                                                        } catch (IOException ex) {
 
1048
                                                                LOG.error(ex);
 
1049
                                                        }
 
1050
                                                        // calculate md5 on the fly
 
1051
                                                        size += data.length;
 
1052
                                                        if (digest != null)
 
1053
                                                                digest.update(data);
939
1054
                                                }
940
 
                                        } else {
941
 
                                                db.rollback();
942
 
                                                messenger.removeQueue(key, randomKey);
943
 
                                                throw new AccessDeniedException("Bucket", bucketName, logData);
944
1055
                                        }
 
1056
                                } catch (InterruptedException ex) {
 
1057
                                        LOG.error(ex, ex);
 
1058
                                        messenger.removeQueue(key, randomKey);
 
1059
                                        throw new EucalyptusCloudException("Transfer interrupted: "
 
1060
                                                        + key + "." + randomKey);
 
1061
                                }
 
1062
                        } else {
 
1063
                                db.rollback();
 
1064
                                messenger.removeQueue(key, randomKey);
 
1065
                                throw new AccessDeniedException("Bucket", bucketName, logData);
 
1066
                        }
945
1067
                } else {
946
1068
                        db.rollback();
947
1069
                        messenger.removeQueue(key, randomKey);
954
1076
                return reply;
955
1077
        }
956
1078
 
 
1079
        private void incrementBucketSize(String bucketName, String objectKey, Long oldBucketSize, Long size) throws EucalyptusCloudException, RollbackException, NoSuchBucketException, EntityTooLargeException {
 
1080
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
 
1081
                try {
 
1082
                        BucketInfo searchBucket = new BucketInfo(bucketName);
 
1083
                        BucketInfo bucket = null;
 
1084
                        try {
 
1085
                                bucket = db.getUnique(searchBucket);
 
1086
                        } catch (EucalyptusCloudException ex) {
 
1087
                                LOG.error(ex);
 
1088
                                throw new NoSuchBucketException(bucketName);
 
1089
                        }
 
1090
                        Long bucketSize = bucket.getBucketSize();
 
1091
                        long newSize = bucketSize + oldBucketSize
 
1092
                                        + size;
 
1093
                        if (WalrusProperties.shouldEnforceUsageLimits
 
1094
                                        && !Contexts.lookup().hasAdministrativePrivileges()) {
 
1095
                                if (newSize > (WalrusInfo.getWalrusInfo().getStorageMaxBucketSizeInMB() * WalrusProperties.M)) {
 
1096
                                        throw new EntityTooLargeException(
 
1097
                                                        "Key", objectKey);
 
1098
                                }
 
1099
                        }
 
1100
                        bucket.setBucketSize(newSize);
 
1101
                        db.commit();
 
1102
                } catch (RollbackException ex) {                        
 
1103
                        throw ex;
 
1104
                } catch (EucalyptusCloudException ex) {
 
1105
                        db.rollback();
 
1106
                        throw ex;
 
1107
                }
 
1108
        }
 
1109
 
957
1110
        public PostObjectResponseType postObject(PostObjectType request)
958
 
        throws EucalyptusCloudException {
 
1111
                        throws EucalyptusCloudException {
959
1112
                PostObjectResponseType reply = (PostObjectResponseType) request
960
 
                .getReply();
 
1113
                                .getReply();
961
1114
 
962
1115
                String bucketName = request.getBucket();
963
1116
                String key = request.getKey();
964
1117
 
965
1118
                PutObjectType putObject = new PutObjectType();
966
 
                putObject.setUserId(request.getUserId());
 
1119
                putObject.setUserId(Contexts.lookup().getUserFullName().getUserId());
967
1120
                putObject.setBucket(bucketName);
968
1121
                putObject.setKey(key);
969
1122
                putObject.setRandomKey(request.getRandomKey());
997
1150
                                LOG.warn(ex);
998
1151
                        }
999
1152
                        String paramString = "bucket=" + bucketName + "&key=" + key
1000
 
                        + "&etag=quot;" + etag + "quot;";
 
1153
                                        + "&etag=quot;" + etag + "quot;";
1001
1154
                        reply.setRedirectUrl(successActionRedirect + "?" + paramString);
1002
1155
                } else {
1003
1156
                        Integer successActionStatus = request.getSuccessActionStatus();
1025
1178
        public PutObjectInlineResponseType putObjectInline(
1026
1179
                        PutObjectInlineType request) throws EucalyptusCloudException {
1027
1180
                PutObjectInlineResponseType reply = (PutObjectInlineResponseType) request
1028
 
                .getReply();
1029
 
                String userId = request.getUserId();
 
1181
                                .getReply();
 
1182
                Context ctx = Contexts.lookup();
 
1183
                Account account = ctx.getAccount();
1030
1184
 
1031
1185
                String bucketName = request.getBucket();
1032
1186
                String objectKey = request.getKey();
1036
1190
                Date lastModified;
1037
1191
 
1038
1192
                AccessControlListType accessControlList = request
1039
 
                .getAccessControlList();
 
1193
                                .getAccessControlList();
1040
1194
                if (accessControlList == null) {
1041
1195
                        accessControlList = new AccessControlListType();
1042
1196
                }
1043
1197
 
1044
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
1198
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
1045
1199
                BucketInfo bucketInfo = new BucketInfo(bucketName);
1046
1200
                List<BucketInfo> bucketList = db.query(bucketInfo);
1047
1201
 
1048
1202
                if (bucketList.size() > 0) {
1049
1203
                        BucketInfo bucket = bucketList.get(0);
1050
 
                        BucketLogData logData = bucket.getLoggingEnabled() ? request
1051
 
                                        .getLogData() : null;
1052
 
                                        if (bucket.canWrite(userId)) {
1053
 
                                                EntityWrapper<ObjectInfo> dbObject = db
 
1204
                        BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
 
1205
                        long objSize = 0;
 
1206
                        try {
 
1207
                                objSize = Long.valueOf( request.getContentLength( ) );
 
1208
                        } catch ( NumberFormatException e ) {
 
1209
                                LOG.error( "Invalid content length " + request.getContentLength( ) );
 
1210
                                // TODO(wenye): should handle this properly.
 
1211
                                objSize = 1L;
 
1212
                        }
 
1213
                        if (ctx.hasAdministrativePrivileges() || (
 
1214
                                        bucket.canWrite(account.getAccountNumber()) &&
 
1215
                                        (bucket.isGlobalWrite() || Lookups.checkPrivilege(PolicySpec.S3_PUTOBJECT,
 
1216
                                                        PolicySpec.VENDOR_S3,
 
1217
                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
1218
                                                        bucketName,
 
1219
                                                        null)))) {
 
1220
                                EntityWrapper<ObjectInfo> dbObject = db
1054
1221
                                                .recast(ObjectInfo.class);
1055
 
                                                ObjectInfo searchObjectInfo = new ObjectInfo();
1056
 
                                                searchObjectInfo.setBucketName(bucketName);
 
1222
                                ObjectInfo searchObjectInfo = new ObjectInfo();
 
1223
                                searchObjectInfo.setBucketName(bucketName);
1057
1224
 
1058
 
                                                ObjectInfo foundObject = null;
1059
 
                                                List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
1060
 
                                                for (ObjectInfo objectInfo : objectInfos) {
1061
 
                                                        if (objectInfo.getObjectKey().equals(objectKey)) {
1062
 
                                                                // key (object) exists. check perms
1063
 
                                                                if (!objectInfo.canWrite(userId)) {
1064
 
                                                                        db.rollback();
1065
 
                                                                        throw new AccessDeniedException("Key", objectKey,
1066
 
                                                                                        logData);
1067
 
                                                                }
1068
 
                                                                foundObject = objectInfo;
1069
 
                                                                oldBucketSize = -foundObject.getSize();
1070
 
                                                                break;
1071
 
                                                        }
1072
 
                                                }
1073
 
                                                // write object to bucket
1074
 
                                                String objectName;
1075
 
                                                if (foundObject == null) {
1076
 
                                                        // not found. create an object info
1077
 
                                                        foundObject = new ObjectInfo(bucketName, objectKey);
1078
 
                                                        foundObject.setOwnerId(userId);
1079
 
                                                        List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
1080
 
                                                        foundObject
1081
 
                                                        .addGrants(userId, grantInfos, accessControlList);
1082
 
                                                        foundObject.setGrants(grantInfos);
1083
 
                                                        objectName = UUID.randomUUID().toString();
1084
 
                                                        foundObject.setObjectName(objectName);
1085
 
                                                        dbObject.add(foundObject);
1086
 
                                                } else {
1087
 
                                                        // object already exists. see if we can modify acl
1088
 
                                                        if (foundObject.canWriteACP(userId)) {
1089
 
                                                                List<GrantInfo> grantInfos = foundObject.getGrants();
1090
 
                                                                foundObject.addGrants(userId, grantInfos,
1091
 
                                                                                accessControlList);
1092
 
                                                        }
1093
 
                                                        objectName = foundObject.getObjectName();
1094
 
                                                }
1095
 
                                                foundObject.setObjectKey(objectKey);
 
1225
                                ObjectInfo foundObject = null;
 
1226
                                List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
 
1227
                                for (ObjectInfo objectInfo : objectInfos) {
 
1228
                                        if (objectInfo.getObjectKey().equals(objectKey)) {
 
1229
                                                // key (object) exists. check perms
 
1230
                                                if (!objectInfo.canWrite(account.getAccountNumber())) {
 
1231
                                                        db.rollback();
 
1232
                                                        throw new AccessDeniedException("Key", objectKey,
 
1233
                                                                        logData);
 
1234
                                                }
 
1235
                                                foundObject = objectInfo;
 
1236
                                                oldBucketSize = -foundObject.getSize();
 
1237
                                                break;
 
1238
                                        }
 
1239
                                }
 
1240
                                // write object to bucket
 
1241
                                String objectName;
 
1242
                                if (foundObject == null) {
 
1243
                                        // not found. create an object info
 
1244
                                        foundObject = new ObjectInfo(bucketName, objectKey);
 
1245
                                        foundObject.setOwnerId(account.getAccountNumber());
 
1246
                                        List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
 
1247
                                        foundObject
 
1248
                                        .addGrants(account.getAccountNumber(), grantInfos, accessControlList);
 
1249
                                        foundObject.setGrants(grantInfos);
 
1250
                                        objectName = UUID.randomUUID().toString();
 
1251
                                        foundObject.setObjectName(objectName);
 
1252
                                        dbObject.add(foundObject);
 
1253
                                } else {
 
1254
                                        // object already exists. see if we can modify acl
 
1255
                                        if (ctx.hasAdministrativePrivileges() || foundObject.canWriteACP(account.getAccountNumber())) {
 
1256
                                                List<GrantInfo> grantInfos = foundObject.getGrants();
 
1257
                                                foundObject.addGrants(account.getAccountNumber(), grantInfos,
 
1258
                                                                accessControlList);
 
1259
                                        }
 
1260
                                        objectName = foundObject.getObjectName();
 
1261
                                }
 
1262
                                foundObject.setObjectKey(objectKey);
 
1263
                                try {
 
1264
                                        // writes are unconditional
 
1265
                                        if (request.getBase64Data().getBytes().length > WalrusProperties.MAX_INLINE_DATA_SIZE) {
 
1266
                                                db.rollback();
 
1267
                                                throw new InlineDataTooLargeException(bucketName + "/"
 
1268
                                                                + objectKey);
 
1269
                                        }
 
1270
                                        byte[] base64Data = Hashes.base64decode(
 
1271
                                                        request.getBase64Data()).getBytes();
 
1272
                                        foundObject.setObjectName(objectName);
 
1273
                                        try {
 
1274
                                                FileIO fileIO = storageManager.prepareForWrite(
 
1275
                                                                bucketName, objectName);
 
1276
                                                if (fileIO != null) {
 
1277
                                                        fileIO.write(base64Data);
 
1278
                                                        fileIO.finish();
 
1279
                                                }
 
1280
                                        } catch (Exception ex) {
 
1281
                                                db.rollback();
 
1282
                                                throw new EucalyptusCloudException(ex);
 
1283
                                        }
 
1284
                                        md5 = Hashes.getHexString(Digest.MD5.get().digest(
 
1285
                                                        base64Data));
 
1286
                                        foundObject.setEtag(md5);
 
1287
                                        Long size = (long) base64Data.length;
 
1288
                                        foundObject.setSize(size);
 
1289
                                        if (!ctx.hasAdministrativePrivileges() &&
 
1290
                                                        !Permissions.canAllocate(PolicySpec.VENDOR_S3,
 
1291
                                                                        PolicySpec.S3_RESOURCE_OBJECT,
 
1292
                                                                        bucketName,
 
1293
                                                                        PolicySpec.S3_PUTOBJECT,
 
1294
                                                                        ctx.getUser(),
 
1295
                                                                        oldBucketSize + size)) {
 
1296
                                                db.rollback();
 
1297
                                                LOG.error("Quota exceeded in Walrus putObject");
 
1298
                                                throw new EntityTooLargeException("Key", objectKey, logData);
 
1299
                                        }
 
1300
                                        boolean success = false;
 
1301
                                        int retryCount = 0;
 
1302
                                        do {
1096
1303
                                                try {
1097
 
                                                        // writes are unconditional
1098
 
                                                        if (request.getBase64Data().getBytes().length > WalrusProperties.MAX_INLINE_DATA_SIZE) {
1099
 
                                                                db.rollback();
1100
 
                                                                throw new InlineDataTooLargeException(bucketName + "/"
1101
 
                                                                                + objectKey);
1102
 
                                                        }
1103
 
                                                        byte[] base64Data = Hashes.base64decode(
1104
 
                                                                        request.getBase64Data()).getBytes();
1105
 
                                                        foundObject.setObjectName(objectName);
1106
 
                                                        try {
1107
 
                                                                FileIO fileIO = storageManager.prepareForWrite(
1108
 
                                                                                bucketName, objectName);
1109
 
                                                                if (fileIO != null) {
1110
 
                                                                        fileIO.write(base64Data);
1111
 
                                                                        fileIO.finish();
1112
 
                                                                }
1113
 
                                                        } catch (Exception ex) {
1114
 
                                                                db.rollback();
1115
 
                                                                throw new EucalyptusCloudException(ex);
1116
 
                                                        }
1117
 
                                                        md5 = Hashes.getHexString(Digest.MD5.get().digest(
1118
 
                                                                        base64Data));
1119
 
                                                        foundObject.setEtag(md5);
1120
 
                                                        Long size = (long) base64Data.length;
1121
 
                                                        foundObject.setSize(size);
1122
 
                                                        if (WalrusProperties.shouldEnforceUsageLimits
1123
 
                                                                        && !request.isAdministrator()) {
1124
 
                                                                Long bucketSize = bucket.getBucketSize();
1125
 
                                                                long newSize = bucketSize + oldBucketSize + size;
1126
 
                                                                if (newSize > (WalrusInfo.getWalrusInfo().getStorageMaxBucketSizeInMB() * WalrusProperties.M)) {
1127
 
                                                                        db.rollback();
1128
 
                                                                        throw new EntityTooLargeException("Key", objectKey,
1129
 
                                                                                        logData);
1130
 
                                                                }
1131
 
                                                                bucket.setBucketSize(newSize);
1132
 
                                                        }
1133
 
                                                        if (WalrusProperties.trackUsageStatistics) {
1134
 
                                                                walrusStatistics.updateBytesIn(size);
1135
 
                                                                walrusStatistics.updateSpaceUsed(size);
1136
 
                                                        }
1137
 
                                                        // Add meta data if specified
1138
 
                                                        if (request.getMetaData() != null)
1139
 
                                                                foundObject.replaceMetaData(request.getMetaData());
 
1304
                                                        incrementBucketSize(bucketName, objectKey, oldBucketSize, size);
 
1305
                                                        success = true;
 
1306
                                                } catch (EntityTooLargeException ex) {
 
1307
                                                        db.rollback();
 
1308
                                                        throw ex;
 
1309
                                                } catch (NoSuchBucketException ex) {
 
1310
                                                        db.rollback();
 
1311
                                                        throw ex;
 
1312
                                                } catch (RollbackException ex) {
 
1313
                                                        retryCount++;
 
1314
                                                        LOG.trace("retrying update: " + bucketName);
 
1315
                                                } catch (EucalyptusCloudException ex) {
 
1316
                                                        db.rollback();
 
1317
                                                        throw ex;
 
1318
                                                }
 
1319
                                        } while(!success && (retryCount < 5));
 
1320
                                        if (WalrusProperties.trackUsageStatistics) {
 
1321
                                                walrusStatistics.updateBytesIn(size);
 
1322
                                                walrusStatistics.updateSpaceUsed(size);
 
1323
                                        }
 
1324
                                        // Add meta data if specified
 
1325
                                        if (request.getMetaData() != null)
 
1326
                                                foundObject.replaceMetaData(request.getMetaData());
1140
1327
 
1141
 
                                                        // TODO: add support for other storage classes
1142
 
                                                        foundObject.setStorageClass("STANDARD");
1143
 
                                                        lastModified = new Date();
1144
 
                                                        foundObject.setLastModified(lastModified);
1145
 
                                                        if (logData != null) {
1146
 
                                                                updateLogData(bucket, logData);
1147
 
                                                                logData.setObjectSize(size);
1148
 
                                                                reply.setLogData(logData);
1149
 
                                                        }
1150
 
                                                } catch (Exception ex) {
1151
 
                                                        LOG.error(ex);
1152
 
                                                        db.rollback();
1153
 
                                                        throw new EucalyptusCloudException(bucketName);
1154
 
                                                }
1155
 
                                        } else {
1156
 
                                                db.rollback();
1157
 
                                                throw new AccessDeniedException("Bucket", bucketName, logData);
 
1328
                                        // TODO: add support for other storage classes
 
1329
                                        foundObject.setStorageClass("STANDARD");
 
1330
                                        lastModified = new Date();
 
1331
                                        foundObject.setLastModified(lastModified);
 
1332
                                        if (logData != null) {
 
1333
                                                updateLogData(bucket, logData);
 
1334
                                                logData.setObjectSize(size);
 
1335
                                                reply.setLogData(logData);
1158
1336
                                        }
 
1337
                                        QueueSender queueSender =
 
1338
                                                        QueueFactory.getInstance()
 
1339
                                                        .getSender(QueueIdentifier.S3);
 
1340
                                        queueSender.send(new S3Event(true,
 
1341
                                                        size / WalrusProperties.M,
 
1342
                                                        ctx.getUser().getUserId(),
 
1343
                                                        ctx.getUser().getName(),
 
1344
                                                        ctx.getAccount().getAccountNumber(),
 
1345
                                                        ctx.getAccount().getName()));
 
1346
                                } catch (Exception ex) {
 
1347
                                        LOG.error(ex);
 
1348
                                        db.rollback();
 
1349
                                        throw new EucalyptusCloudException(bucketName);
 
1350
                                }
 
1351
                        } else {
 
1352
                                db.rollback();
 
1353
                                throw new AccessDeniedException("Bucket", bucketName, logData);
 
1354
                        }
1159
1355
                } else {
1160
1356
                        db.rollback();
1161
1357
                        throw new NoSuchBucketException(bucketName);
1171
1367
        }
1172
1368
 
1173
1369
        public AddObjectResponseType addObject(AddObjectType request)
1174
 
        throws EucalyptusCloudException {
 
1370
                        throws EucalyptusCloudException {
1175
1371
 
1176
1372
                AddObjectResponseType reply = (AddObjectResponseType) request
1177
 
                .getReply();
 
1373
                                .getReply();
1178
1374
                String bucketName = request.getBucket();
1179
1375
                String key = request.getKey();
1180
 
                String userId = request.getUserId();
 
1376
                Context ctx = Contexts.lookup();
 
1377
                Account account = ctx.getAccount();
1181
1378
                String objectName = request.getObjectName();
1182
1379
 
1183
1380
                AccessControlListType accessControlList = request
1184
 
                .getAccessControlList();
 
1381
                                .getAccessControlList();
1185
1382
                if (accessControlList == null) {
1186
1383
                        accessControlList = new AccessControlListType();
1187
1384
                }
1188
1385
 
1189
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
1386
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
1190
1387
                BucketInfo bucketInfo = new BucketInfo(bucketName);
1191
1388
                List<BucketInfo> bucketList = db.query(bucketInfo);
1192
1389
 
1193
1390
                if (bucketList.size() > 0) {
1194
1391
                        BucketInfo bucket = bucketList.get(0);
1195
 
                        if (bucket.canWrite(userId)) {
 
1392
                        if (ctx.hasAdministrativePrivileges() || (
 
1393
                                        bucket.canWrite(account.getAccountNumber()) &&
 
1394
                                        (bucket.isGlobalWrite() || Lookups.checkPrivilege(PolicySpec.S3_PUTOBJECT,
 
1395
                                                        PolicySpec.VENDOR_S3,
 
1396
                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
1397
                                                        bucket.getBucketName(),
 
1398
                                                        null)))) {
1196
1399
                                EntityWrapper<ObjectInfo> dbObject = db
1197
 
                                .recast(ObjectInfo.class);
 
1400
                                                .recast(ObjectInfo.class);
1198
1401
                                ObjectInfo searchObjectInfo = new ObjectInfo();
1199
1402
                                searchObjectInfo.setBucketName(bucketName);
1200
1403
                                List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
1210
1413
                                ObjectInfo objectInfo = new ObjectInfo(bucketName, key);
1211
1414
                                objectInfo.setObjectName(objectName);
1212
1415
                                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
1213
 
                                objectInfo.addGrants(userId, grantInfos, accessControlList);
 
1416
                                objectInfo.addGrants(account.getAccountNumber(), grantInfos, accessControlList);
1214
1417
                                objectInfo.setGrants(grantInfos);
1215
1418
                                dbObject.add(objectInfo);
1216
1419
 
1217
1420
                                objectInfo.setObjectKey(key);
1218
 
                                objectInfo.setOwnerId(userId);
 
1421
                                objectInfo.setOwnerId(account.getAccountNumber());
1219
1422
                                objectInfo.setSize(storageManager.getSize(bucketName,
1220
1423
                                                objectName));
1221
1424
                                objectInfo.setEtag(request.getEtag());
1234
1437
        }
1235
1438
 
1236
1439
        public DeleteObjectResponseType deleteObject(DeleteObjectType request)
1237
 
        throws EucalyptusCloudException {
1238
 
                DeleteObjectResponseType reply = (DeleteObjectResponseType) request
1239
 
                .getReply();
 
1440
                        throws EucalyptusCloudException {
 
1441
                DeleteObjectResponseType reply = (DeleteObjectResponseType) request.getReply();
1240
1442
                String bucketName = request.getBucket();
1241
1443
                String objectKey = request.getKey();
1242
 
                String userId = request.getUserId();
 
1444
                Context ctx = Contexts.lookup();
 
1445
                Account account = ctx.getAccount();
1243
1446
 
1244
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
1447
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
1245
1448
                BucketInfo bucketInfos = new BucketInfo(bucketName);
1246
1449
                List<BucketInfo> bucketList = db.query(bucketInfos);
1247
1450
 
1248
1451
                if (bucketList.size() > 0) {
1249
1452
                        BucketInfo bucketInfo = bucketList.get(0);
1250
 
                        BucketLogData logData = bucketInfo.getLoggingEnabled() ? request
1251
 
                                        .getLogData() : null;
1252
 
 
1253
 
                                        if(bucketInfo.isVersioningEnabled()) {
1254
 
                                                EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
1255
 
                                                ObjectInfo searchDeletedObjectInfo = new ObjectInfo(bucketName, objectKey);
1256
 
                                                searchDeletedObjectInfo.setDeleted(true);
1257
 
                                                try {
1258
 
                                                        dbObject.getUnique(searchDeletedObjectInfo);
1259
 
                                                        db.rollback();
1260
 
                                                        throw new NoSuchEntityException(objectKey, logData);
1261
 
                                                } catch(NoSuchEntityException ex) {
1262
 
                                                        throw ex;
1263
 
                                                } catch(EucalyptusCloudException ex) {
1264
 
                                                        ObjectInfo searchObjectInfo = new ObjectInfo(bucketName, objectKey);
1265
 
                                                        searchObjectInfo.setLast(true);
1266
 
                                                        List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
1267
 
                                                        for(ObjectInfo objInfo : objectInfos) {
1268
 
                                                                objInfo.setLast(false);
 
1453
                        BucketLogData logData = bucketInfo.getLoggingEnabled() ? request.getLogData() : null;
 
1454
                        if (ctx.hasAdministrativePrivileges() || (
 
1455
                                        bucketInfo.canWrite(account.getAccountNumber()) &&
 
1456
                                        (bucketInfo.isGlobalWrite() || Lookups.checkPrivilege(PolicySpec.S3_DELETEOBJECT,
 
1457
                                                        PolicySpec.VENDOR_S3,
 
1458
                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
1459
                                                        bucketInfo.getBucketName(),
 
1460
                                                        null)))) {
 
1461
                                if(bucketInfo.isVersioningEnabled()) {
 
1462
                                        EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
 
1463
                                        ObjectInfo searchDeletedObjectInfo = new ObjectInfo(bucketName, objectKey);
 
1464
                                        searchDeletedObjectInfo.setDeleted(true);
 
1465
                                        try {
 
1466
                                                dbObject.getUnique(searchDeletedObjectInfo);
 
1467
                                                db.rollback();
 
1468
                                                throw new NoSuchEntityException(objectKey, logData);
 
1469
                                        } catch(NoSuchEntityException ex) {
 
1470
                                                throw ex;
 
1471
                                        } catch(EucalyptusCloudException ex) {
 
1472
                                                ObjectInfo searchObjectInfo = new ObjectInfo(bucketName, objectKey);
 
1473
                                                searchObjectInfo.setLast(true);
 
1474
                                                List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
 
1475
                                                for(ObjectInfo objInfo : objectInfos) {
 
1476
                                                        objInfo.setLast(false);
 
1477
                                                }
 
1478
                                                ObjectInfo deleteMarker = new ObjectInfo(bucketName, objectKey);
 
1479
                                                deleteMarker.setDeleted(true);
 
1480
                                                deleteMarker.setLast(true);
 
1481
                                                deleteMarker.setOwnerId(account.getAccountNumber());
 
1482
                                                deleteMarker.setLastModified(new Date());
 
1483
                                                deleteMarker.setVersionId(UUID.randomUUID().toString().replaceAll("-", ""));
 
1484
                                                dbObject.add(deleteMarker);
 
1485
                                                reply.setCode("200");
 
1486
                                                reply.setDescription("OK");
 
1487
                                        }
 
1488
                                } else {
 
1489
                                        //versioning disabled or suspended.
 
1490
                                        ObjectInfo searchObjectInfo = new ObjectInfo(bucketName, objectKey);
 
1491
                                        searchObjectInfo.setVersionId(WalrusProperties.NULL_VERSION_ID);
 
1492
                                        EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
 
1493
                                        List<ObjectInfo>objectInfos = dbObject.query(searchObjectInfo);
 
1494
                                        if (objectInfos.size() > 0) {
 
1495
                                                ObjectInfo nullObject = objectInfos.get(0);
 
1496
                                                dbObject.delete(nullObject);
 
1497
                                                String objectName = nullObject.getObjectName();
 
1498
                                                for (GrantInfo grantInfo : nullObject.getGrants()) {
 
1499
                                                        db.delete(grantInfo);
 
1500
                                                }
 
1501
                                                Long size = nullObject.getSize();
 
1502
                                                boolean success = false;
 
1503
                                                int retryCount = 0;
 
1504
                                                do {
 
1505
                                                        try {
 
1506
                                                                decrementBucketSize(bucketName, size);
 
1507
                                                                success = true;
 
1508
                                                        } catch (NoSuchBucketException ex) {
 
1509
                                                                db.rollback();
 
1510
                                                                throw ex;
 
1511
                                                        } catch (RollbackException ex) {
 
1512
                                                                retryCount++;
 
1513
                                                                LOG.trace("retrying update: " + bucketName);
 
1514
                                                        } catch (EucalyptusCloudException ex) {
 
1515
                                                                db.rollback();
 
1516
                                                                throw ex;
1269
1517
                                                        }
1270
 
                                                        ObjectInfo deleteMarker = new ObjectInfo(bucketName,
1271
 
                                                                        objectKey);
 
1518
                                                } while(!success && (retryCount < 5));
 
1519
                                                ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, 
 
1520
                                                                objectName, 
 
1521
                                                                size, 
 
1522
                                                                ctx.getUser().getName(),
 
1523
                                                                ctx.getUser().getUserId(),
 
1524
                                                                ctx.getAccount().getName(),
 
1525
                                                                ctx.getAccount().getAccountNumber());
 
1526
                                                Threads.lookup(Walrus.class, WalrusManager.ObjectDeleter.class).limitTo(10).submit(objectDeleter);
 
1527
                                                reply.setCode("200");
 
1528
                                                reply.setDescription("OK");
 
1529
                                                if (logData != null) {
 
1530
                                                        updateLogData(bucketInfo, logData);
 
1531
                                                        reply.setLogData(logData);
 
1532
                                                }
 
1533
                                                if(bucketInfo.isVersioningSuspended()) {
 
1534
                                                        //add delete marker
 
1535
                                                        ObjectInfo deleteMarker = new ObjectInfo(bucketName, objectKey);
1272
1536
                                                        deleteMarker.setDeleted(true);
1273
1537
                                                        deleteMarker.setLast(true);
1274
 
                                                        deleteMarker.setOwnerId(userId);
 
1538
                                                        deleteMarker.setOwnerId(account.getAccountNumber());
1275
1539
                                                        deleteMarker.setLastModified(new Date());
1276
1540
                                                        deleteMarker.setVersionId(UUID.randomUUID().toString().replaceAll("-", ""));
1277
1541
                                                        dbObject.add(deleteMarker);
1278
 
                                                        reply.setCode("200");
1279
 
                                                        reply.setDescription("OK");
1280
1542
                                                }
1281
1543
                                        } else {
1282
 
                                                //versioning disabled or suspended.
1283
 
                                                ObjectInfo searchObjectInfo = new ObjectInfo(bucketName, objectKey);
1284
 
                                                searchObjectInfo.setVersionId(WalrusProperties.NULL_VERSION_ID);
1285
 
                                                EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
1286
 
                                                List<ObjectInfo>objectInfos = dbObject.query(searchObjectInfo);
1287
 
                                                if (objectInfos.size() > 0) {
1288
 
                                                        ObjectInfo nullObject = objectInfos.get(0);
1289
 
                                                        if(nullObject.canWrite(userId)) {
1290
 
                                                                dbObject.delete(nullObject);
1291
 
                                                                String objectName = nullObject.getObjectName();
1292
 
                                                                for (GrantInfo grantInfo : nullObject
1293
 
                                                                                .getGrants()) {
1294
 
                                                                        db.getEntityManager().remove(grantInfo);
1295
 
                                                                }
1296
 
                                                                Long size = nullObject.getSize();
1297
 
                                                                bucketInfo.setBucketSize(bucketInfo
1298
 
                                                                                .getBucketSize()
1299
 
                                                                                - size);
1300
 
                                                                ObjectDeleter objectDeleter = new ObjectDeleter(
1301
 
                                                                                bucketName, objectName, size);
1302
 
                                                                objectDeleter.start();
1303
 
                                                                reply.setCode("200");
1304
 
                                                                reply.setDescription("OK");
1305
 
                                                                if (logData != null) {
1306
 
                                                                        updateLogData(bucketInfo, logData);
1307
 
                                                                        reply.setLogData(logData);
1308
 
                                                                }
1309
 
                                                                if(bucketInfo.isVersioningSuspended()) {
1310
 
                                                                        //add delete marker
1311
 
                                                                        ObjectInfo deleteMarker = new ObjectInfo(bucketName,
1312
 
                                                                                        objectKey);
1313
 
                                                                        deleteMarker.setDeleted(true);
1314
 
                                                                        deleteMarker.setLast(true);
1315
 
                                                                        deleteMarker.setOwnerId(userId);
1316
 
                                                                        deleteMarker.setLastModified(new Date());
1317
 
                                                                        deleteMarker.setVersionId(UUID.randomUUID().toString().replaceAll("-", ""));
1318
 
                                                                        dbObject.add(deleteMarker);
1319
 
                                                                }
1320
 
                                                        } else {
1321
 
                                                                db.rollback();
1322
 
                                                                throw new AccessDeniedException("Key", objectKey, logData);
1323
 
                                                        }
1324
 
                                                } else {
1325
 
                                                        db.rollback();
1326
 
                                                        throw new NoSuchEntityException(objectKey, logData);
1327
 
                                                }
 
1544
                                                db.rollback();
 
1545
                                                throw new NoSuchEntityException(objectKey, logData);
1328
1546
                                        }
 
1547
                                }
 
1548
                        } else {
 
1549
                                db.rollback();
 
1550
                                throw new AccessDeniedException("Bucket", bucketName, logData);                   
 
1551
                        }
1329
1552
                } else {
1330
1553
                        db.rollback();
1331
1554
                        throw new NoSuchBucketException(bucketName);
1334
1557
                return reply;
1335
1558
        }
1336
1559
 
1337
 
        private class ObjectDeleter extends Thread {
 
1560
        private void decrementBucketSize(String bucketName, Long size) throws EucalyptusCloudException, RollbackException, NoSuchBucketException {
 
1561
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
 
1562
                try {
 
1563
                        BucketInfo searchBucket = new BucketInfo(bucketName);
 
1564
                        BucketInfo bucket = null;
 
1565
                        try {
 
1566
                                bucket = db.getUnique(searchBucket);
 
1567
                        } catch (EucalyptusCloudException ex) {
 
1568
                                LOG.error(ex);
 
1569
                                throw new NoSuchBucketException(bucketName);
 
1570
                        }
 
1571
                        Long bucketSize = bucket.getBucketSize();
 
1572
                        long newSize = bucketSize - size;
 
1573
                        bucket.setBucketSize(newSize);
 
1574
                        db.commit();
 
1575
                } catch (RollbackException ex) {                        
 
1576
                        throw ex;
 
1577
                } catch (EucalyptusCloudException ex) {
 
1578
                        db.rollback();
 
1579
                        throw ex;
 
1580
                }
 
1581
        }
 
1582
 
 
1583
 
 
1584
        private class ObjectDeleter implements Runnable {
1338
1585
                String bucketName;
1339
1586
                String objectName;
1340
1587
                Long size;
 
1588
                String user;
 
1589
                String userId;
 
1590
                String account;
 
1591
                String accountNumber;
1341
1592
 
1342
 
                public ObjectDeleter(String bucketName, String objectName, Long size) {
 
1593
                public ObjectDeleter(String bucketName, String objectName, Long size, String user, String userId, String account, String accountNumber) {
1343
1594
                        this.bucketName = bucketName;
1344
1595
                        this.objectName = objectName;
1345
1596
                        this.size = size;
 
1597
                        this.user = user;
 
1598
                        this.userId = userId;
 
1599
                        this.account = account;
 
1600
                        this.accountNumber = accountNumber;
1346
1601
                }
1347
1602
 
1348
1603
                public void run() {
1350
1605
                                storageManager.deleteObject(bucketName, objectName);
1351
1606
                                if (WalrusProperties.trackUsageStatistics && (size > 0))
1352
1607
                                        walrusStatistics.updateSpaceUsed(-size);
 
1608
                                QueueSender queueSender =
 
1609
                                                QueueFactory.getInstance()
 
1610
                                                .getSender(QueueIdentifier.S3);
 
1611
                                queueSender.send(new S3Event(false,
 
1612
                                                size / WalrusProperties.M, userId, user,
 
1613
                                                accountNumber, account));                       
1353
1614
                        } catch (IOException ex) {
1354
1615
                                LOG.error(ex, ex);
1355
1616
                        }
1357
1618
        }
1358
1619
 
1359
1620
        public ListBucketResponseType listBucket(ListBucketType request)
1360
 
        throws EucalyptusCloudException {
 
1621
                        throws EucalyptusCloudException {
1361
1622
                ListBucketResponseType reply = (ListBucketResponseType) request
1362
 
                .getReply();
 
1623
                                .getReply();
1363
1624
                String bucketName = request.getBucket();
1364
 
                String userId = request.getUserId();
 
1625
                Context ctx = Contexts.lookup();
 
1626
                Account account = ctx.getAccount();
1365
1627
                String prefix = request.getPrefix();
1366
1628
                if (prefix == null)
1367
1629
                        prefix = "";
1376
1638
 
1377
1639
                String delimiter = request.getDelimiter();
1378
1640
 
1379
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
1641
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
1380
1642
                BucketInfo bucketInfo = new BucketInfo(bucketName);
1381
1643
                bucketInfo.setHidden(false);
1382
1644
                List<BucketInfo> bucketList = db.query(bucketInfo);
1387
1649
                        BucketInfo bucket = bucketList.get(0);
1388
1650
                        BucketLogData logData = bucket.getLoggingEnabled() ? request
1389
1651
                                        .getLogData() : null;
1390
 
                                        if (bucket.canRead(userId)) {
 
1652
                                        if (ctx.hasAdministrativePrivileges() || (
 
1653
                                                        bucket.canRead(account.getAccountNumber()) &&
 
1654
                                                        (bucket.isGlobalRead() || Lookups.checkPrivilege(PolicySpec.S3_LISTBUCKET,
 
1655
                                                                        PolicySpec.VENDOR_S3,
 
1656
                                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
1657
                                                                        bucketName,
 
1658
                                                                        null)))) {
1391
1659
                                                if (logData != null) {
1392
1660
                                                        updateLogData(bucket, logData);
1393
1661
                                                        reply.setLogData(logData);
1394
1662
                                                }
1395
 
                                                if (request.isAdministrator()) {
 
1663
                                                if (Contexts.lookup().hasAdministrativePrivileges()) {
1396
1664
                                                        EntityWrapper<WalrusSnapshotInfo> dbSnap = db
1397
 
                                                        .recast(WalrusSnapshotInfo.class);
 
1665
                                                                        .recast(WalrusSnapshotInfo.class);
1398
1666
                                                        WalrusSnapshotInfo walrusSnapInfo = new WalrusSnapshotInfo();
1399
1667
                                                        walrusSnapInfo.setSnapshotBucket(bucketName);
1400
1668
                                                        List<WalrusSnapshotInfo> walrusSnaps = dbSnap
1401
 
                                                        .query(walrusSnapInfo);
 
1669
                                                                        .query(walrusSnapInfo);
1402
1670
                                                        if (walrusSnaps.size() > 0) {
1403
1671
                                                                db.rollback();
1404
1672
                                                                throw new NoSuchBucketException(bucketName);
1413
1681
                                                if (delimiter != null)
1414
1682
                                                        reply.setDelimiter(delimiter);
1415
1683
                                                EntityWrapper<ObjectInfo> dbObject = db
1416
 
                                                .recast(ObjectInfo.class);
 
1684
                                                                .recast(ObjectInfo.class);
1417
1685
                                                ObjectInfo searchObjectInfo = new ObjectInfo();
1418
1686
                                                searchObjectInfo.setBucketName(bucketName);
1419
1687
                                                searchObjectInfo.setDeleted(false);
1439
1707
                                                                                                        prefix.length()).split(delimiter);
1440
1708
                                                                                        if (parts.length > 1) {
1441
1709
                                                                                                String prefixString = parts[0]
1442
 
                                                                                                                            + delimiter;
 
1710
                                                                                                                + delimiter;
1443
1711
                                                                                                boolean foundPrefix = false;
1444
1712
                                                                                                for (PrefixEntry prefixEntry : prefixes) {
1445
1713
                                                                                                        if (prefixEntry.getPrefix().equals(
1477
1745
                                                                                DateUtils.ISO8601_DATETIME_PATTERN)
1478
1746
                                                                                + ".000Z");
1479
1747
                                                                listEntry.setStorageClass(objectInfo.getStorageClass());
 
1748
                                                                // displayName is actually the owner account ID
1480
1749
                                                                String displayName = objectInfo.getOwnerId();
1481
1750
                                                                try {
1482
 
                                                                        User userInfo = Users.lookupUser(displayName);
1483
 
                                                                        listEntry.setOwner(new CanonicalUserType(userInfo
1484
 
                                                                                        .getQueryId(), displayName));
1485
 
                                                                } catch (NoSuchUserException e) {
 
1751
                                                                        listEntry.setOwner(new CanonicalUserType(Accounts.lookupAccountById(displayName).getName(), displayName));
 
1752
                                                                } catch (AuthException e) {
1486
1753
                                                                        db.rollback();
1487
1754
                                                                        throw new AccessDeniedException("Bucket",
1488
1755
                                                                                        bucketName, logData);
1513
1780
 
1514
1781
        public GetObjectAccessControlPolicyResponseType getObjectAccessControlPolicy(
1515
1782
                        GetObjectAccessControlPolicyType request)
1516
 
        throws EucalyptusCloudException {
 
1783
                                        throws EucalyptusCloudException {
1517
1784
                GetObjectAccessControlPolicyResponseType reply = (GetObjectAccessControlPolicyResponseType) request
1518
 
                .getReply();
 
1785
                                .getReply();
1519
1786
 
1520
1787
                String bucketName = request.getBucket();
1521
1788
                String objectKey = request.getKey();
1522
 
                String userId = request.getUserId();
 
1789
                Context ctx = Contexts.lookup();
 
1790
                Account account = ctx.getAccount();
1523
1791
                String ownerId = null;
1524
1792
 
1525
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
1793
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
1526
1794
                BucketInfo bucketInfo = new BucketInfo(bucketName);
1527
1795
                List<BucketInfo> bucketList = db.query(bucketInfo);
1528
1796
                BucketLogData logData;
1545
1813
                                        List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
1546
1814
                                        if (objectInfos.size() > 0) {
1547
1815
                                                ObjectInfo objectInfo = objectInfos.get(0);
1548
 
                                                if (objectInfo.canReadACP(userId)) {
 
1816
                                                if (ctx.hasAdministrativePrivileges( ) || (
 
1817
                                                                objectInfo.canReadACP(account.getAccountNumber()) &&
 
1818
                                                                (objectInfo.isGlobalReadACP() || Lookups.checkPrivilege(PolicySpec.S3_GETOBJECTACL,
 
1819
                                                                                PolicySpec.VENDOR_S3,
 
1820
                                                                                PolicySpec.S3_RESOURCE_OBJECT,
 
1821
                                                                                PolicySpec.objectFullName(bucketName, objectKey),
 
1822
                                                                                null)))) {
1549
1823
                                                        if (logData != null) {
1550
1824
                                                                updateLogData(bucket, logData);
1551
1825
                                                                logData.setObjectSize(objectInfo.getSize());
1558
1832
                                                        for (GrantInfo grantInfo : grantInfos) {
1559
1833
                                                                String uId = grantInfo.getUserId();
1560
1834
                                                                try {
1561
 
                                                                        User userInfo = Users.lookupUser(uId);
1562
1835
                                                                        objectInfo.readPermissions(grants);
1563
 
                                                                        addPermission(grants, userInfo, grantInfo);
1564
 
                                                                } catch (NoSuchUserException e) {
 
1836
                                                                        addPermission(grants, Accounts.lookupAccountById(uId), grantInfo);
 
1837
                                                                } catch (AuthException e) {
1565
1838
                                                                        throw new AccessDeniedException("Key", objectKey,
1566
1839
                                                                                        logData);
1567
1840
                                                                }
1582
1855
 
1583
1856
                AccessControlPolicyType accessControlPolicy = new AccessControlPolicyType();
1584
1857
                try {
1585
 
                        User ownerUserInfo = Users.lookupUser(ownerId);
1586
 
                        accessControlPolicy.setOwner(new CanonicalUserType(ownerUserInfo
1587
 
                                        .getQueryId(), ownerUserInfo.getName()));
 
1858
                        Account ownerInfo = Accounts.lookupAccountById(ownerId);
 
1859
                        accessControlPolicy.setOwner(new CanonicalUserType(ownerInfo.getName(), ownerInfo.getAccountNumber()));
1588
1860
                        accessControlPolicy.setAccessControlList(accessControlList);
1589
 
                } catch (NoSuchUserException e) {
 
1861
                } catch (AuthException e) {
1590
1862
                        throw new AccessDeniedException("Key", objectKey, logData);
1591
1863
                }
1592
1864
                reply.setAccessControlPolicy(accessControlPolicy);
1596
1868
 
1597
1869
        public SetBucketAccessControlPolicyResponseType setBucketAccessControlPolicy(
1598
1870
                        SetBucketAccessControlPolicyType request)
1599
 
        throws EucalyptusCloudException {
 
1871
                                        throws EucalyptusCloudException {
1600
1872
                SetBucketAccessControlPolicyResponseType reply = (SetBucketAccessControlPolicyResponseType) request
1601
 
                .getReply();
1602
 
                String userId = request.getUserId();
 
1873
                                .getReply();
 
1874
                Context ctx = Contexts.lookup();
 
1875
                Account account = ctx.getAccount();
1603
1876
                AccessControlListType accessControlList = request
1604
 
                .getAccessControlList();
 
1877
                                .getAccessControlList();
1605
1878
                String bucketName = request.getBucket();
1606
1879
                if (accessControlList == null) {
1607
1880
                        throw new AccessDeniedException("Bucket", bucketName);
1608
1881
                }
1609
1882
 
1610
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
1883
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
1611
1884
                BucketInfo bucketInfo = new BucketInfo(bucketName);
1612
1885
                List<BucketInfo> bucketList = db.query(bucketInfo);
1613
1886
 
1614
1887
                if (bucketList.size() > 0) {
1615
1888
                        BucketInfo bucket = bucketList.get(0);
1616
 
                        BucketLogData logData = bucket.getLoggingEnabled() ? request
1617
 
                                        .getLogData() : null;
1618
 
                                        if (bucket.canWriteACP(userId)) {
1619
 
                                                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
1620
 
                                                bucket.resetGlobalGrants();
1621
 
                                                bucket.addGrants(bucket.getOwnerId(), grantInfos,
1622
 
                                                                accessControlList);
1623
 
                                                bucket.setGrants(grantInfos);
1624
 
                                                reply.setCode("204");
1625
 
                                                reply.setDescription("OK");
1626
 
                                                if (logData != null) {
1627
 
                                                        updateLogData(bucket, logData);
1628
 
                                                        reply.setLogData(logData);
1629
 
                                                }
1630
 
                                        } else {
1631
 
                                                db.rollback();
1632
 
                                                throw new AccessDeniedException("Bucket", bucketName, logData);
1633
 
                                        }
 
1889
                        BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
 
1890
                        if (ctx.hasAdministrativePrivileges() || (
 
1891
                                        bucket.canWriteACP(account.getAccountNumber()) &&
 
1892
                                        (bucket.isGlobalWriteACP() || Lookups.checkPrivilege(PolicySpec.S3_PUTBUCKETACL,
 
1893
                                                        PolicySpec.VENDOR_S3,
 
1894
                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
1895
                                                        bucketName,
 
1896
                                                        null)))) {
 
1897
                                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
 
1898
                                bucket.resetGlobalGrants();
 
1899
                                bucket.addGrants(bucket.getOwnerId(), grantInfos, accessControlList);
 
1900
                                bucket.setGrants(grantInfos);
 
1901
                                reply.setCode("204");
 
1902
                                reply.setDescription("OK");
 
1903
                                if (logData != null) {
 
1904
                                        updateLogData(bucket, logData);
 
1905
                                        reply.setLogData(logData);
 
1906
                                }
 
1907
                        } else {
 
1908
                                db.rollback();
 
1909
                                throw new AccessDeniedException("Bucket", bucketName, logData);
 
1910
                        }
1634
1911
                } else {
1635
1912
                        db.rollback();
1636
1913
                        throw new NoSuchBucketException(bucketName);
1641
1918
 
1642
1919
        public SetRESTBucketAccessControlPolicyResponseType setRESTBucketAccessControlPolicy(
1643
1920
                        SetRESTBucketAccessControlPolicyType request)
1644
 
        throws EucalyptusCloudException {
 
1921
                                        throws EucalyptusCloudException {
1645
1922
                SetRESTBucketAccessControlPolicyResponseType reply = (SetRESTBucketAccessControlPolicyResponseType) request
1646
 
                .getReply();
1647
 
                String userId = request.getUserId();
 
1923
                                .getReply();
 
1924
                Context ctx = Contexts.lookup();
 
1925
                Account account = ctx.getAccount();
1648
1926
                AccessControlPolicyType accessControlPolicy = request
1649
 
                .getAccessControlPolicy();
 
1927
                                .getAccessControlPolicy();
1650
1928
                String bucketName = request.getBucket();
1651
1929
                if (accessControlPolicy == null) {
1652
1930
                        throw new AccessDeniedException("Bucket", bucketName);
1653
1931
                }
1654
1932
                AccessControlListType accessControlList = accessControlPolicy
1655
 
                .getAccessControlList();
 
1933
                                .getAccessControlList();
1656
1934
 
1657
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
1935
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
1658
1936
                BucketInfo bucketInfo = new BucketInfo(bucketName);
1659
1937
                List<BucketInfo> bucketList = db.query(bucketInfo);
1660
1938
 
1661
1939
                if (bucketList.size() > 0) {
1662
1940
                        BucketInfo bucket = bucketList.get(0);
1663
 
                        BucketLogData logData = bucket.getLoggingEnabled() ? request
1664
 
                                        .getLogData() : null;
1665
 
                                        if (bucket.canWriteACP(userId)) {
1666
 
                                                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
1667
 
                                                bucket.resetGlobalGrants();
1668
 
                                                bucket.addGrants(bucket.getOwnerId(), grantInfos,
1669
 
                                                                accessControlList);
1670
 
                                                bucket.setGrants(grantInfos);
1671
 
                                                reply.setCode("204");
1672
 
                                                reply.setDescription("OK");
1673
 
                                                if (logData != null) {
1674
 
                                                        updateLogData(bucket, logData);
1675
 
                                                        reply.setLogData(logData);
1676
 
                                                }
1677
 
                                        } else {
1678
 
                                                db.rollback();
1679
 
                                                throw new AccessDeniedException("Bucket", bucketName, logData);
1680
 
                                        }
 
1941
                        BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
 
1942
                        if (ctx.hasAdministrativePrivileges() || (
 
1943
                                        bucket.canWriteACP(account.getAccountNumber()) &&
 
1944
                                        (bucket.isGlobalWriteACP() || Lookups.checkPrivilege(PolicySpec.S3_PUTBUCKETACL,
 
1945
                                                        PolicySpec.VENDOR_S3,
 
1946
                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
1947
                                                        bucketName,
 
1948
                                                        null)))) {
 
1949
                                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
 
1950
                                bucket.resetGlobalGrants();
 
1951
                                bucket.addGrants(bucket.getOwnerId(), grantInfos,
 
1952
                                                accessControlList);
 
1953
                                bucket.setGrants(grantInfos);
 
1954
                                reply.setCode("204");
 
1955
                                reply.setDescription("OK");
 
1956
                                if (logData != null) {
 
1957
                                        updateLogData(bucket, logData);
 
1958
                                        reply.setLogData(logData);
 
1959
                                }
 
1960
                        } else {
 
1961
                                db.rollback();
 
1962
                                throw new AccessDeniedException("Bucket", bucketName, logData);
 
1963
                        }
1681
1964
                } else {
1682
1965
                        db.rollback();
1683
1966
                        throw new NoSuchBucketException(bucketName);
1688
1971
 
1689
1972
        public SetObjectAccessControlPolicyResponseType setObjectAccessControlPolicy(
1690
1973
                        SetObjectAccessControlPolicyType request)
1691
 
        throws EucalyptusCloudException {
 
1974
                                        throws EucalyptusCloudException {
1692
1975
                SetObjectAccessControlPolicyResponseType reply = (SetObjectAccessControlPolicyResponseType) request
1693
 
                .getReply();
1694
 
                String userId = request.getUserId();
 
1976
                                .getReply();
 
1977
                Context ctx = Contexts.lookup();
 
1978
                Account account = ctx.getAccount();
1695
1979
                AccessControlListType accessControlList = request
1696
 
                .getAccessControlList();
 
1980
                                .getAccessControlList();
1697
1981
                String bucketName = request.getBucket();
1698
1982
                String objectKey = request.getKey();
1699
1983
 
1700
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
1984
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
1701
1985
                BucketInfo bucketInfo = new BucketInfo(bucketName);
1702
1986
                List<BucketInfo> bucketList = db.query(bucketInfo);
1703
1987
 
1717
2001
                                        List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
1718
2002
                                        if (objectInfos.size() > 0) {
1719
2003
                                                ObjectInfo objectInfo = objectInfos.get(0);
1720
 
                                                if (!objectInfo.canWriteACP(userId)) {
 
2004
                                                if (!ctx.hasAdministrativePrivileges() && !(
 
2005
                                                                objectInfo.canWriteACP(account.getAccountNumber()) &&
 
2006
                                                                (objectInfo.isGlobalWriteACP() || Lookups.checkPrivilege(PolicySpec.S3_PUTOBJECTACL,
 
2007
                                                                                PolicySpec.VENDOR_S3,
 
2008
                                                                                PolicySpec.S3_RESOURCE_OBJECT,
 
2009
                                                                                PolicySpec.objectFullName(bucketName, objectKey),
 
2010
                                                                                null)))) {
1721
2011
                                                        db.rollback();
1722
2012
                                                        throw new AccessDeniedException("Key", objectKey, logData);
1723
2013
                                                }
1730
2020
                                                if (WalrusProperties.enableTorrents) {
1731
2021
                                                        if (!objectInfo.isGlobalRead()) {
1732
2022
                                                                EntityWrapper<TorrentInfo> dbTorrent = db
1733
 
                                                                .recast(TorrentInfo.class);
 
2023
                                                                                .recast(TorrentInfo.class);
1734
2024
                                                                TorrentInfo torrentInfo = new TorrentInfo(bucketName,
1735
2025
                                                                                objectKey);
1736
2026
                                                                List<TorrentInfo> torrentInfos = dbTorrent
1737
 
                                                                .query(torrentInfo);
 
2027
                                                                                .query(torrentInfo);
1738
2028
                                                                if (torrentInfos.size() > 0) {
1739
2029
                                                                        TorrentInfo foundTorrentInfo = torrentInfos.get(0);
1740
2030
                                                                        TorrentClient torrentClient = Torrents
1741
 
                                                                        .getClient(bucketName + objectKey);
 
2031
                                                                                        .getClient(bucketName + objectKey);
1742
2032
                                                                        if (torrentClient != null) {
1743
2033
                                                                                torrentClient.bye();
1744
2034
                                                                        }
1769
2059
 
1770
2060
        public SetRESTObjectAccessControlPolicyResponseType setRESTObjectAccessControlPolicy(
1771
2061
                        SetRESTObjectAccessControlPolicyType request)
1772
 
        throws EucalyptusCloudException {
 
2062
                                        throws EucalyptusCloudException {
1773
2063
                SetRESTObjectAccessControlPolicyResponseType reply = (SetRESTObjectAccessControlPolicyResponseType) request
1774
 
                .getReply();
1775
 
                String userId = request.getUserId();
 
2064
                                .getReply();
 
2065
                Context ctx = Contexts.lookup();
 
2066
                Account account = ctx.getAccount();
1776
2067
                AccessControlPolicyType accessControlPolicy = request
1777
 
                .getAccessControlPolicy();
 
2068
                                .getAccessControlPolicy();
1778
2069
                if (accessControlPolicy == null) {
1779
2070
                        throw new AccessDeniedException("Key", request.getKey());
1780
2071
                }
1781
2072
                AccessControlListType accessControlList = accessControlPolicy
1782
 
                .getAccessControlList();
 
2073
                                .getAccessControlList();
1783
2074
                String bucketName = request.getBucket();
1784
2075
                String objectKey = request.getKey();
1785
2076
 
1786
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
2077
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
1787
2078
                BucketInfo bucketInfo = new BucketInfo(bucketName);
1788
2079
                List<BucketInfo> bucketList = db.query(bucketInfo);
1789
2080
 
1803
2094
                                        List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
1804
2095
                                        if (objectInfos.size() > 0) {
1805
2096
                                                ObjectInfo objectInfo = objectInfos.get(0);
1806
 
                                                if (!objectInfo.canWriteACP(userId)) {
 
2097
                                                if (!ctx.hasAdministrativePrivileges() && !(
 
2098
                                                                objectInfo.canWriteACP(account.getAccountNumber()) &&
 
2099
                                                                (objectInfo.isGlobalWriteACP() || Lookups.checkPrivilege(PolicySpec.S3_PUTOBJECTACL,
 
2100
                                                                                PolicySpec.VENDOR_S3,
 
2101
                                                                                PolicySpec.S3_RESOURCE_OBJECT,
 
2102
                                                                                PolicySpec.objectFullName(bucketName, objectKey),
 
2103
                                                                                null)))) {
1807
2104
                                                        db.rollback();
1808
2105
                                                        throw new AccessDeniedException("Key", objectKey, logData);
1809
2106
                                                }
1816
2113
                                                if (WalrusProperties.enableTorrents) {
1817
2114
                                                        if (!objectInfo.isGlobalRead()) {
1818
2115
                                                                EntityWrapper<TorrentInfo> dbTorrent = db
1819
 
                                                                .recast(TorrentInfo.class);
 
2116
                                                                                .recast(TorrentInfo.class);
1820
2117
                                                                TorrentInfo torrentInfo = new TorrentInfo(bucketName,
1821
2118
                                                                                objectKey);
1822
2119
                                                                List<TorrentInfo> torrentInfos = dbTorrent
1823
 
                                                                .query(torrentInfo);
 
2120
                                                                                .query(torrentInfo);
1824
2121
                                                                if (torrentInfos.size() > 0) {
1825
2122
                                                                        TorrentInfo foundTorrentInfo = torrentInfos.get(0);
1826
2123
                                                                        TorrentClient torrentClient = Torrents
1827
 
                                                                        .getClient(bucketName + objectKey);
 
2124
                                                                                        .getClient(bucketName + objectKey);
1828
2125
                                                                        if (torrentClient != null) {
1829
2126
                                                                                torrentClient.bye();
1830
2127
                                                                        }
1855
2152
        }
1856
2153
 
1857
2154
        public GetObjectResponseType getObject(GetObjectType request)
1858
 
        throws EucalyptusCloudException {
 
2155
                        throws EucalyptusCloudException {
1859
2156
                GetObjectResponseType reply = (GetObjectResponseType) request
1860
 
                .getReply();
 
2157
                                .getReply();
1861
2158
                String bucketName = request.getBucket();
1862
2159
                String objectKey = request.getKey();
1863
 
                String userId = request.getUserId();
 
2160
                Context ctx = Contexts.lookup();
 
2161
                Account account = ctx.getAccount();
1864
2162
                Boolean deleteAfterGet = request.getDeleteAfterGet();
1865
2163
                if (deleteAfterGet == null)
1866
2164
                        deleteAfterGet = false;
1873
2171
                if (getMetaData == null)
1874
2172
                        getMetaData = false;
1875
2173
 
1876
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
2174
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
1877
2175
                BucketInfo bucketInfo = new BucketInfo(bucketName);
1878
2176
                List<BucketInfo> bucketList = db.query(bucketInfo);
1879
2177
 
1893
2191
                                        List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
1894
2192
                                        if (objectInfos.size() > 0) {
1895
2193
                                                ObjectInfo objectInfo = objectInfos.get(0);
1896
 
                                                if (objectInfo.canRead(userId)) {
 
2194
                                                if (ctx.hasAdministrativePrivileges() || (
 
2195
                                                                objectInfo.canRead(account.getAccountNumber()) &&
 
2196
                                                                (objectInfo.isGlobalRead() || Lookups.checkPrivilege(PolicySpec.S3_GETOBJECT,
 
2197
                                                                                PolicySpec.VENDOR_S3,
 
2198
                                                                                PolicySpec.S3_RESOURCE_OBJECT,
 
2199
                                                                                PolicySpec.objectFullName(bucketName, objectKey),
 
2200
                                                                                null)))) {
1897
2201
                                                        String objectName = objectInfo.getObjectName();
1898
2202
                                                        DefaultHttpResponse httpResponse = new DefaultHttpResponse(
1899
2203
                                                                        HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
1900
2204
                                                        if (getMetaData) {
1901
2205
                                                                List<MetaDataInfo> metaDataInfos = objectInfo
1902
 
                                                                .getMetaData();
 
2206
                                                                                .getMetaData();
1903
2207
                                                                for (MetaDataInfo metaDataInfo : metaDataInfos) {
1904
2208
                                                                        httpResponse.addHeader(
1905
2209
                                                                                        WalrusProperties.AMZ_META_HEADER_PREFIX
1913
2217
                                                                                LOG
1914
2218
                                                                                .warn("Bittorrent support has been disabled. Please check pre-requisites");
1915
2219
                                                                                throw new EucalyptusCloudException(
1916
 
                                                                                "Torrents disabled");
 
2220
                                                                                                "Torrents disabled");
1917
2221
                                                                        }
1918
 
                                                                        EntityWrapper<TorrentInfo> dbTorrent = WalrusControl
1919
 
                                                                        .getEntityWrapper();
 
2222
                                                                        EntityWrapper<TorrentInfo> dbTorrent = EntityWrapper.get(TorrentInfo.class);
1920
2223
                                                                        TorrentInfo torrentInfo = new TorrentInfo(
1921
2224
                                                                                        bucketName, objectKey);
1922
2225
                                                                        TorrentInfo foundTorrentInfo;
1923
2226
                                                                        String absoluteObjectPath = storageManager
1924
 
                                                                        .getObjectPath(bucketName, objectName);
 
2227
                                                                                        .getObjectPath(bucketName, objectName);
1925
2228
                                                                        try {
1926
2229
                                                                                foundTorrentInfo = dbTorrent
1927
 
                                                                                .getUnique(torrentInfo);
 
2230
                                                                                                .getUnique(torrentInfo);
1928
2231
                                                                        } catch (EucalyptusCloudException ex) {
1929
2232
                                                                                String torrentFile = objectName + ".torrent";
1930
2233
                                                                                String torrentFilePath = storageManager
1931
 
                                                                                .getObjectPath(bucketName, torrentFile);
 
2234
                                                                                                .getObjectPath(bucketName, torrentFile);
1932
2235
                                                                                TorrentCreator torrentCreator = new TorrentCreator(
1933
2236
                                                                                                absoluteObjectPath, objectKey,
1934
2237
                                                                                                objectName, torrentFilePath,
1939
2242
                                                                                        LOG.error(e);
1940
2243
                                                                                        throw new EucalyptusCloudException(
1941
2244
                                                                                                        "could not create torrent file "
1942
 
                                                                                                        + torrentFile);
 
2245
                                                                                                                        + torrentFile);
1943
2246
                                                                                }
1944
2247
                                                                                torrentInfo.setTorrentFile(torrentFile);
1945
2248
                                                                                dbTorrent.add(torrentInfo);
1947
2250
                                                                        }
1948
2251
                                                                        dbTorrent.commit();
1949
2252
                                                                        String torrentFile = foundTorrentInfo
1950
 
                                                                        .getTorrentFile();
 
2253
                                                                                        .getTorrentFile();
1951
2254
                                                                        String torrentFilePath = storageManager
1952
 
                                                                        .getObjectPath(bucketName, torrentFile);
 
2255
                                                                                        .getObjectPath(bucketName, torrentFile);
1953
2256
                                                                        TorrentClient torrentClient = new TorrentClient(
1954
2257
                                                                                        torrentFilePath, absoluteObjectPath);
1955
2258
                                                                        Torrents.addClient(bucketName + objectKey,
1963
2266
                                                                        File torrent = new File(torrentFilePath);
1964
2267
                                                                        if (torrent.exists()) {
1965
2268
                                                                                Date lastModified = objectInfo
1966
 
                                                                                .getLastModified();
 
2269
                                                                                                .getLastModified();
1967
2270
                                                                                db.commit();
1968
2271
                                                                                long torrentLength = torrent.length();
1969
2272
                                                                                if (logData != null) {
1986
2289
                                                                                                                + ".000Z",
1987
2290
                                                                                                                "application/x-bittorrent",
1988
2291
                                                                                                                "attachment; filename="
1989
 
                                                                                                                + objectKey
1990
 
                                                                                                                + ".torrent;", request
1991
 
                                                                                                                .getIsCompressed(),
1992
 
                                                                                                                null, logData);
 
2292
                                                                                                                                + objectKey
 
2293
                                                                                                                                + ".torrent;", request
 
2294
                                                                                                                                .getIsCompressed(),
 
2295
                                                                                                                                null, logData);
1993
2296
                                                                                if (WalrusProperties.trackUsageStatistics) {
1994
2297
                                                                                        walrusStatistics
1995
2298
                                                                                        .updateBytesOut(torrentLength);
1998
2301
                                                                        } else {
1999
2302
                                                                                db.rollback();
2000
2303
                                                                                String errorString = "Could not get torrent file "
2001
 
                                                                                        + torrentFilePath;
 
2304
                                                                                                + torrentFilePath;
2002
2305
                                                                                LOG.error(errorString);
2003
2306
                                                                                throw new EucalyptusCloudException(errorString);
2004
2307
                                                                        }
2013
2316
                                                        String etag = objectInfo.getEtag();
2014
2317
                                                        String contentType = objectInfo.getContentType();
2015
2318
                                                        String contentDisposition = objectInfo
2016
 
                                                        .getContentDisposition();
 
2319
                                                                        .getContentDisposition();
2017
2320
                                                        db.commit();
2018
2321
                                                        if (logData != null) {
2019
2322
                                                                updateLogData(bucket, logData);
2097
2400
                                                }
2098
2401
                                        } else {
2099
2402
                                                db.rollback();
2100
 
                                                throw new NoSuchEntityException(objectKey, logData);
 
2403
                                                throw new AccessDeniedException("Key", objectKey, logData);
2101
2404
                                        }
2102
2405
                } else {
2103
2406
                        db.rollback();
2108
2411
        public GetObjectExtendedResponseType getObjectExtended(
2109
2412
                        GetObjectExtendedType request) throws EucalyptusCloudException {
2110
2413
                GetObjectExtendedResponseType reply = (GetObjectExtendedResponseType) request
2111
 
                .getReply();
2112
 
                Long byteRangeStart = request.getByteRangeStart();
2113
 
                if (byteRangeStart == null) {
2114
 
                        byteRangeStart = 0L;
2115
 
                }
2116
 
                Long byteRangeEnd = request.getByteRangeEnd();
2117
 
                if (byteRangeEnd == null) {
2118
 
                        byteRangeEnd = -1L;
2119
 
                }
 
2414
                                .getReply();
2120
2415
                Date ifModifiedSince = request.getIfModifiedSince();
2121
2416
                Date ifUnmodifiedSince = request.getIfUnmodifiedSince();
2122
2417
                String ifMatch = request.getIfMatch();
2123
2418
                String ifNoneMatch = request.getIfNoneMatch();
2124
2419
                boolean returnCompleteObjectOnFailure = request
2125
 
                .getReturnCompleteObjectOnConditionFailure();
 
2420
                                .getReturnCompleteObjectOnConditionFailure();
2126
2421
 
2127
2422
                String bucketName = request.getBucket();
2128
2423
                String objectKey = request.getKey();
2129
 
                String userId = request.getUserId();
 
2424
                Context ctx = Contexts.lookup();
 
2425
                Account account = ctx.getAccount();
2130
2426
                Status status = new Status();
2131
2427
 
2132
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
2428
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
2133
2429
                BucketInfo bucketInfo = new BucketInfo(bucketName);
2134
2430
                List<BucketInfo> bucketList = db.query(bucketInfo);
2135
2431
 
2146
2442
                                        if (objectInfos.size() > 0) {
2147
2443
                                                ObjectInfo objectInfo = objectInfos.get(0);
2148
2444
 
2149
 
                                                if (objectInfo.canRead(userId)) {
 
2445
                                                if (ctx.hasAdministrativePrivileges() || (
 
2446
                                                                objectInfo.canRead(account.getAccountNumber()) &&
 
2447
                                                                (objectInfo.isGlobalRead() || Lookups.checkPrivilege(PolicySpec.S3_GETOBJECT,
 
2448
                                                                                PolicySpec.VENDOR_S3,
 
2449
                                                                                PolicySpec.S3_RESOURCE_OBJECT,
 
2450
                                                                                PolicySpec.objectFullName(bucketName, objectKey),
 
2451
                                                                                null)))) {
2150
2452
                                                        String etag = objectInfo.getEtag();
2151
2453
                                                        String objectName = objectInfo.getObjectName();
 
2454
                                                        Long byteRangeStart = request.getByteRangeStart();                                                      
 
2455
                                                        Long byteRangeEnd = request.getByteRangeEnd();
 
2456
                                                        DefaultHttpResponse httpResponse = null;
 
2457
                                                        if(byteRangeStart != null || byteRangeEnd != null) {
 
2458
                                                                httpResponse = new DefaultHttpResponse(
 
2459
                                                                                HttpVersion.HTTP_1_1, HttpResponseStatus.PARTIAL_CONTENT);
 
2460
                                                        } else {
 
2461
                                                                httpResponse = new DefaultHttpResponse(
 
2462
                                                                                HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
 
2463
                                                        }
 
2464
                                                        if (byteRangeStart == null) {
 
2465
                                                                byteRangeStart = 0L;
 
2466
                                                        }
 
2467
                                                        if (byteRangeEnd == null) {
 
2468
                                                                byteRangeEnd = -1L;
 
2469
                                                        }
 
2470
 
2152
2471
                                                        if (byteRangeEnd == -1)
2153
 
                                                                byteRangeEnd = objectInfo.getSize();
 
2472
                                                                byteRangeEnd = objectInfo.getSize() - 1;
2154
2473
                                                        if ((byteRangeStart > objectInfo.getSize())
2155
2474
                                                                        || (byteRangeStart > byteRangeEnd)
2156
 
                                                                        || (byteRangeEnd > objectInfo.getSize())
 
2475
                                                                        || ((byteRangeEnd + 1) > objectInfo.getSize())
2157
2476
                                                                        || (byteRangeStart < 0 || byteRangeEnd < 0)) {
2158
2477
                                                                throw new InvalidRangeException("Range: "
2159
2478
                                                                                + byteRangeStart + "-" + byteRangeEnd
2160
2479
                                                                                + "object: " + bucketName + "/" + objectKey);
2161
2480
                                                        }
2162
 
                                                        DefaultHttpResponse httpResponse = new DefaultHttpResponse(
2163
 
                                                                        HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
2164
2481
                                                        if (ifMatch != null) {
2165
2482
                                                                if (!ifMatch.equals(etag)
2166
2483
                                                                                && !returnCompleteObjectOnFailure) {
2201
2518
                                                        }
2202
2519
                                                        if (request.getGetMetaData()) {
2203
2520
                                                                List<MetaDataInfo> metaDataInfos = objectInfo
2204
 
                                                                .getMetaData();
 
2521
                                                                                .getMetaData();
2205
2522
                                                                for (MetaDataInfo metaDataInfo : metaDataInfos) {
2206
2523
                                                                        httpResponse.addHeader(
2207
2524
                                                                                        WalrusProperties.AMZ_META_HEADER_PREFIX
2212
2529
                                                        Long size = objectInfo.getSize();
2213
2530
                                                        String contentType = objectInfo.getContentType();
2214
2531
                                                        String contentDisposition = objectInfo
2215
 
                                                        .getContentDisposition();
 
2532
                                                                        .getContentDisposition();
2216
2533
                                                        db.commit();
2217
2534
                                                        if (logData != null) {
2218
2535
                                                                updateLogData(bucket, logData);
2230
2547
                                                                }
2231
2548
                                                                storageManager.sendObject(request,
2232
2549
                                                                                httpResponse, bucketName, objectName,
2233
 
                                                                                byteRangeStart, byteRangeEnd, size, etag,
 
2550
                                                                                byteRangeStart, byteRangeEnd + 1, size, etag,
2234
2551
                                                                                DateUtils.format(lastModified.getTime(),
2235
2552
                                                                                                DateUtils.ISO8601_DATETIME_PATTERN
2236
2553
                                                                                                + ".000Z"), contentType,
2248
2565
                                                        }
2249
2566
                                                } else {
2250
2567
                                                        db.rollback();
2251
 
                                                        throw new AccessDeniedException("Key", objectKey);
 
2568
                                                        throw new AccessDeniedException("Key", objectKey, logData);
2252
2569
                                                }
2253
2570
                                        } else {
2254
2571
                                                db.rollback();
2255
 
                                                throw new NoSuchEntityException(objectKey);
 
2572
                                                throw new AccessDeniedException("Key", objectKey, logData);
2256
2573
                                        }
2257
2574
                } else {
2258
2575
                        db.rollback();
2263
2580
        public GetBucketLocationResponseType getBucketLocation(
2264
2581
                        GetBucketLocationType request) throws EucalyptusCloudException {
2265
2582
                GetBucketLocationResponseType reply = (GetBucketLocationResponseType) request
2266
 
                .getReply();
 
2583
                                .getReply();
2267
2584
                String bucketName = request.getBucket();
2268
 
                String userId = request.getUserId();
 
2585
                Context ctx = Contexts.lookup();
 
2586
                Account account = ctx.getAccount();
2269
2587
 
2270
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
2588
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
2271
2589
                BucketInfo bucketInfo = new BucketInfo(bucketName);
2272
2590
                List<BucketInfo> bucketList = db.query(bucketInfo);
2273
2591
 
2274
2592
                if (bucketList.size() > 0) {
2275
2593
                        BucketInfo bucket = bucketList.get(0);
2276
 
                        BucketLogData logData = bucket.getLoggingEnabled() ? request
2277
 
                                        .getLogData() : null;
2278
 
                                        if (bucket.canRead(userId)) {
2279
 
                                                if (logData != null) {
2280
 
                                                        updateLogData(bucket, logData);
2281
 
                                                        reply.setLogData(logData);
2282
 
                                                }
2283
 
                                                String location = bucket.getLocation();
2284
 
                                                if (location == null) {
2285
 
                                                        location = "NotSupported";
2286
 
                                                }
2287
 
                                                reply.setLocationConstraint(location);
2288
 
                                        } else {
2289
 
                                                db.rollback();
2290
 
                                                throw new AccessDeniedException("Bucket", bucketName, logData);
2291
 
                                        }
 
2594
                        BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
 
2595
                        if (ctx.hasAdministrativePrivileges() || (
 
2596
                                        bucket.canRead(account.getAccountNumber()) &&
 
2597
                                        (bucket.isGlobalRead() || Lookups.checkPrivilege(PolicySpec.S3_GETBUCKETLOCATION,
 
2598
                                                        PolicySpec.VENDOR_S3,
 
2599
                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
2600
                                                        bucketName,
 
2601
                                                        null)))) {
 
2602
                                if (logData != null) {
 
2603
                                        updateLogData(bucket, logData);
 
2604
                                        reply.setLogData(logData);
 
2605
                                }
 
2606
                                String location = bucket.getLocation();
 
2607
                                if (location == null) {
 
2608
                                        location = "NotSupported";
 
2609
                                }
 
2610
                                reply.setLocationConstraint(location);
 
2611
                        } else {
 
2612
                                db.rollback();
 
2613
                                throw new AccessDeniedException("Bucket", bucketName, logData);
 
2614
                        }
2292
2615
                } else {
2293
2616
                        db.rollback();
2294
2617
                        throw new NoSuchBucketException(bucketName);
2298
2621
        }
2299
2622
 
2300
2623
        public CopyObjectResponseType copyObject(CopyObjectType request)
2301
 
        throws EucalyptusCloudException {
 
2624
                        throws EucalyptusCloudException {
2302
2625
                CopyObjectResponseType reply = (CopyObjectResponseType) request
2303
 
                .getReply();
2304
 
                String userId = request.getUserId();
 
2626
                                .getReply();
 
2627
                Context ctx = Contexts.lookup();
 
2628
                Account account = ctx.getAccount();
2305
2629
                String sourceBucket = request.getSourceBucket();
2306
2630
                String sourceKey = request.getSourceObject();
2307
2631
                String sourceVersionId = request.getSourceVersionId();
2309
2633
                String destinationKey = request.getDestinationObject();
2310
2634
                String metadataDirective = request.getMetadataDirective();
2311
2635
                AccessControlListType accessControlList = request
2312
 
                .getAccessControlList();
 
2636
                                .getAccessControlList();
2313
2637
 
2314
2638
                String copyIfMatch = request.getCopySourceIfMatch();
2315
2639
                String copyIfNoneMatch = request.getCopySourceIfNoneMatch();
2318
2642
 
2319
2643
                if (metadataDirective == null)
2320
2644
                        metadataDirective = "COPY";
2321
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
2645
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
2322
2646
                BucketInfo bucketInfo = new BucketInfo(sourceBucket);
2323
2647
                List<BucketInfo> bucketList = db.query(bucketInfo);
2324
2648
 
2332
2656
                        List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
2333
2657
                        if (objectInfos.size() > 0) {
2334
2658
                                ObjectInfo sourceObjectInfo = objectInfos.get(0);
2335
 
                                if (sourceObjectInfo.canRead(userId)) {
 
2659
                                if (ctx.hasAdministrativePrivileges() || (
 
2660
                                                sourceObjectInfo.canRead(account.getAccountNumber()) &&
 
2661
                                                (sourceObjectInfo.isGlobalRead() || Lookups.checkPrivilege(PolicySpec.S3_GETOBJECT,
 
2662
                                                                PolicySpec.VENDOR_S3,
 
2663
                                                                PolicySpec.S3_RESOURCE_OBJECT,
 
2664
                                                                PolicySpec.objectFullName(sourceBucket, sourceKey),
 
2665
                                                                null)))) {
2336
2666
                                        if (copyIfMatch != null) {
2337
2667
                                                if (!copyIfMatch.equals(sourceObjectInfo.getEtag())) {
2338
2668
                                                        db.rollback();
2351
2681
                                        if (copyIfUnmodifiedSince != null) {
2352
2682
                                                long unmodifiedTime = copyIfUnmodifiedSince.getTime();
2353
2683
                                                long objectTime = sourceObjectInfo.getLastModified()
2354
 
                                                .getTime();
 
2684
                                                                .getTime();
2355
2685
                                                if (unmodifiedTime < objectTime) {
2356
2686
                                                        db.rollback();
2357
2687
                                                        throw new PreconditionFailedException(sourceKey
2362
2692
                                        if (copyIfModifiedSince != null) {
2363
2693
                                                long modifiedTime = copyIfModifiedSince.getTime();
2364
2694
                                                long objectTime = sourceObjectInfo.getLastModified()
2365
 
                                                .getTime();
 
2695
                                                                .getTime();
2366
2696
                                                if (modifiedTime > objectTime) {
2367
2697
                                                        db.rollback();
2368
2698
                                                        throw new PreconditionFailedException(sourceKey
2373
2703
                                        BucketInfo destinationBucketInfo = new BucketInfo(
2374
2704
                                                        destinationBucket);
2375
2705
                                        List<BucketInfo> destinationBuckets = db
2376
 
                                        .query(destinationBucketInfo);
 
2706
                                                        .query(destinationBucketInfo);
2377
2707
                                        if (destinationBuckets.size() > 0) {
2378
 
                                                BucketInfo foundDestinationBucketInfo = destinationBuckets
2379
 
                                                .get(0);
2380
 
                                                if (foundDestinationBucketInfo.canWrite(userId)) {
 
2708
                                                BucketInfo foundDestinationBucketInfo = destinationBuckets.get(0);
 
2709
                                                if (ctx.hasAdministrativePrivileges() || (
 
2710
                                                                foundDestinationBucketInfo.canWrite(account.getAccountNumber()) &&
 
2711
                                                                (foundDestinationBucketInfo.isGlobalWrite() || Lookups.checkPrivilege(PolicySpec.S3_PUTOBJECT,
 
2712
                                                                                PolicySpec.VENDOR_S3,
 
2713
                                                                                PolicySpec.S3_RESOURCE_BUCKET,
 
2714
                                                                                destinationBucket,
 
2715
                                                                                null)))) {
2381
2716
                                                        // all ok
2382
2717
                                                        String destinationVersionId = sourceVersionId;
2383
2718
                                                        ObjectInfo destinationObjectInfo = null;
2394
2729
                                                        }
2395
2730
                                                        destSearchObjectInfo.setVersionId(destinationVersionId);
2396
2731
                                                        List<ObjectInfo> destinationObjectInfos = dbObject
2397
 
                                                        .query(destSearchObjectInfo);
 
2732
                                                                        .query(destSearchObjectInfo);
2398
2733
                                                        if (destinationObjectInfos.size() > 0) {
2399
2734
                                                                destinationObjectInfo = destinationObjectInfos
2400
 
                                                                .get(0);
2401
 
                                                                if (!destinationObjectInfo.canWrite(userId)) {
 
2735
                                                                                .get(0);
 
2736
                                                                if (!destinationObjectInfo.canWrite(account.getAccountNumber())) {
2402
2737
                                                                        db.rollback();
2403
2738
                                                                        throw new AccessDeniedException("Key",
2404
2739
                                                                                        destinationKey);
2407
2742
                                                        boolean addNew = false;                                         
2408
2743
                                                        if (destinationObjectInfo == null) {
2409
2744
                                                                // not found. create a new one
2410
 
                                                                addNew = true;
2411
 
                                                                destinationObjectInfo = new ObjectInfo();
2412
 
                                                                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
2413
 
                                                                destinationObjectInfo
2414
 
                                                                .setBucketName(destinationBucket);
2415
 
                                                                destinationObjectInfo
2416
 
                                                                .setObjectKey(destinationKey);
2417
 
                                                                destinationObjectInfo.addGrants(userId,
2418
 
                                                                                grantInfos, accessControlList);
2419
 
                                                                destinationObjectInfo.setGrants(grantInfos);
2420
 
                                                                destinationObjectInfo
2421
 
                                                                .setObjectName(UUID.randomUUID().toString());
 
2745
                                                                if (ctx.hasAdministrativePrivileges() || (
 
2746
                                                                                Permissions.isAuthorized(PolicySpec.VENDOR_S3,
 
2747
                                                                                                PolicySpec.S3_RESOURCE_OBJECT,
 
2748
                                                                                                sourceBucket,
 
2749
                                                                                                ctx.getAccount(),
 
2750
                                                                                                PolicySpec.S3_PUTOBJECT,
 
2751
                                                                                                ctx.getUser()) &&
 
2752
                                                                                                Permissions.canAllocate(PolicySpec.VENDOR_S3,
 
2753
                                                                                                                PolicySpec.S3_RESOURCE_OBJECT,
 
2754
                                                                                                                sourceBucket,
 
2755
                                                                                                                PolicySpec.S3_PUTOBJECT,
 
2756
                                                                                                                ctx.getUser(),
 
2757
                                                                                                                sourceObjectInfo.getSize()))) {
 
2758
                                                                        addNew = true;
 
2759
                                                                        destinationObjectInfo = new ObjectInfo();
 
2760
                                                                        List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
 
2761
                                                                        destinationObjectInfo
 
2762
                                                                        .setBucketName(destinationBucket);
 
2763
                                                                        destinationObjectInfo
 
2764
                                                                        .setObjectKey(destinationKey);
 
2765
                                                                        destinationObjectInfo.addGrants(account.getAccountNumber(),
 
2766
                                                                                        grantInfos, accessControlList);
 
2767
                                                                        destinationObjectInfo.setGrants(grantInfos);
 
2768
                                                                        destinationObjectInfo
 
2769
                                                                        .setObjectName(UUID.randomUUID().toString());
 
2770
                                                                }
2422
2771
                                                        } else {
2423
 
                                                                if (destinationObjectInfo.canWriteACP(userId)) {
 
2772
                                                                if (ctx.hasAdministrativePrivileges() || (
 
2773
                                                                                destinationObjectInfo.canWriteACP(account.getAccountNumber()) &&
 
2774
                                                                                (destinationObjectInfo.isGlobalWriteACP() || Lookups.checkPrivilege(PolicySpec.S3_PUTOBJECTACL,
 
2775
                                                                                                PolicySpec.VENDOR_S3,
 
2776
                                                                                                PolicySpec.S3_RESOURCE_OBJECT,
 
2777
                                                                                                PolicySpec.objectFullName(destinationBucket, destinationKey),
 
2778
                                                                                                null)))) {
2424
2779
                                                                        List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
2425
 
                                                                        destinationObjectInfo.addGrants(userId,
 
2780
                                                                        destinationObjectInfo.addGrants(account.getAccountNumber(),
2426
2781
                                                                                        grantInfos, accessControlList);
2427
2782
                                                                        destinationObjectInfo.setGrants(grantInfos);
2428
2783
                                                                }
2442
2797
                                                                        .getContentDisposition());
2443
2798
                                                        String etag = sourceObjectInfo.getEtag();
2444
2799
                                                        Date lastModified = sourceObjectInfo
2445
 
                                                        .getLastModified();
 
2800
                                                                        .getLastModified();
2446
2801
                                                        destinationObjectInfo.setEtag(etag);
2447
2802
                                                        destinationObjectInfo.setLastModified(lastModified);
2448
2803
                                                        destinationObjectInfo.setVersionId(destinationVersionId);
2454
2809
                                                                                .cloneMetaData());
2455
2810
                                                        } else {
2456
2811
                                                                List<MetaDataEntry> metaData = request
2457
 
                                                                .getMetaData();
 
2812
                                                                                .getMetaData();
2458
2813
                                                                if (metaData != null)
2459
2814
                                                                        destinationObjectInfo
2460
2815
                                                                        .replaceMetaData(metaData);
2461
2816
                                                        }
2462
2817
 
2463
2818
                                                        String sourceObjectName = sourceObjectInfo
2464
 
                                                        .getObjectName();
 
2819
                                                                        .getObjectName();
2465
2820
                                                        destinationObjectName = destinationObjectInfo
2466
 
                                                        .getObjectName();
 
2821
                                                                        .getObjectName();
2467
2822
 
2468
2823
                                                        try {
2469
2824
                                                                storageManager.copyObject(sourceBucket,
2533
2888
        public SetBucketLoggingStatusResponseType setBucketLoggingStatus(
2534
2889
                        SetBucketLoggingStatusType request) throws EucalyptusCloudException {
2535
2890
                SetBucketLoggingStatusResponseType reply = (SetBucketLoggingStatusResponseType) request
2536
 
                .getReply();
 
2891
                                .getReply();
2537
2892
                String bucket = request.getBucket();
2538
2893
 
2539
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
2894
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
2540
2895
                BucketInfo bucketInfo, targetBucketInfo;
2541
2896
                try {
2542
2897
                        bucketInfo = db.getUnique(new BucketInfo(bucket));
2550
2905
                        String targetPrefix = request.getLoggingEnabled().getTargetPrefix();
2551
2906
                        List<Grant> targetGrantsList = null;
2552
2907
                        TargetGrants targetGrants = request.getLoggingEnabled()
2553
 
                        .getTargetGrants();
 
2908
                                        .getTargetGrants();
2554
2909
                        if (targetGrants != null)
2555
2910
                                targetGrantsList = targetGrants.getGrants();
2556
2911
                        if (targetPrefix == null)
2581
2936
        public GetBucketLoggingStatusResponseType getBucketLoggingStatus(
2582
2937
                        GetBucketLoggingStatusType request) throws EucalyptusCloudException {
2583
2938
                GetBucketLoggingStatusResponseType reply = (GetBucketLoggingStatusResponseType) request
2584
 
                .getReply();
 
2939
                                .getReply();
2585
2940
                String bucket = request.getBucket();
2586
2941
 
2587
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
2942
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
2588
2943
                try {
2589
2944
                        BucketInfo bucketInfo = db.getUnique(new BucketInfo(bucket));
2590
2945
                        if (bucketInfo.getLoggingEnabled()) {
2598
2953
                                                String uId = grantInfo.getUserId();
2599
2954
                                                try {
2600
2955
                                                        if (uId != null) {
2601
 
                                                                User grantUserInfo = Users.lookupUser(uId);
2602
 
                                                                addPermission(grants, grantUserInfo, grantInfo);
 
2956
                                                                addPermission(grants, Accounts.lookupAccountById(uId), grantInfo);
2603
2957
                                                        } else {
2604
2958
                                                                addPermission(grants, grantInfo);
2605
2959
                                                        }
2606
 
                                                } catch (NoSuchUserException e) {
 
2960
                                                } catch (AuthException e) {
2607
2961
                                                        db.rollback();
2608
2962
                                                        throw new AccessDeniedException("Bucket",
2609
2963
                                                                        targetBucket);
2639
2993
 
2640
2994
        public GetBucketVersioningStatusResponseType getBucketVersioningStatus(
2641
2995
                        GetBucketVersioningStatusType request)
2642
 
        throws EucalyptusCloudException {
 
2996
                                        throws EucalyptusCloudException {
2643
2997
                GetBucketVersioningStatusResponseType reply = (GetBucketVersioningStatusResponseType) request
2644
 
                .getReply();
 
2998
                                .getReply();
2645
2999
                String bucket = request.getBucket();
 
3000
                Context ctx = Contexts.lookup();
2646
3001
 
2647
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
3002
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
2648
3003
                try {
2649
3004
                        BucketInfo bucketInfo = db.getUnique(new BucketInfo(bucket));
2650
 
                        if (bucketInfo.getVersioning() != null) {
2651
 
                                String status = bucketInfo.getVersioning();
2652
 
                                if (WalrusProperties.VersioningStatus.Disabled.toString()
2653
 
                                                .equals(status))
2654
 
                                        reply
2655
 
                                        .setVersioningStatus(WalrusProperties.VersioningStatus.Suspended
2656
 
                                                        .toString());
2657
 
                                else
2658
 
                                        reply.setVersioningStatus(status);
 
3005
                        if (ctx.hasAdministrativePrivileges() ||
 
3006
                                        Lookups.checkPrivilege(PolicySpec.S3_GETBUCKETVERSIONING,
 
3007
                                                        PolicySpec.VENDOR_S3,
 
3008
                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
3009
                                                        bucket,
 
3010
                                                        bucketInfo.getOwnerId())) {
 
3011
                                if (bucketInfo.getVersioning() != null) {
 
3012
                                        String status = bucketInfo.getVersioning();
 
3013
                                        if (WalrusProperties.VersioningStatus.Disabled.toString()
 
3014
                                                        .equals(status))
 
3015
                                                reply
 
3016
                                                .setVersioningStatus(WalrusProperties.VersioningStatus.Suspended
 
3017
                                                                .toString());
 
3018
                                        else
 
3019
                                                reply.setVersioningStatus(status);
 
3020
                                }
 
3021
                        } else {
 
3022
                                LOG.error( "Not authorized to get bucket version status by " + ctx.getUserFullName( ) );
 
3023
                                db.rollback();
 
3024
                                throw new AccessDeniedException("Bucket", bucketInfo.getBucketName( ) );                          
2659
3025
                        }
2660
3026
                } catch (EucalyptusCloudException ex) {
2661
3027
                        db.rollback();
2667
3033
 
2668
3034
        public SetBucketVersioningStatusResponseType setBucketVersioningStatus(
2669
3035
                        SetBucketVersioningStatusType request)
2670
 
        throws EucalyptusCloudException {
 
3036
                                        throws EucalyptusCloudException {
2671
3037
                SetBucketVersioningStatusResponseType reply = (SetBucketVersioningStatusResponseType) request
2672
 
                .getReply();
 
3038
                                .getReply();
2673
3039
                String bucket = request.getBucket();
2674
3040
 
2675
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
3041
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
2676
3042
                BucketInfo bucketInfo;
2677
3043
                try {
2678
3044
                        bucketInfo = db.getUnique(new BucketInfo(bucket));
2701
3067
        }
2702
3068
 
2703
3069
        public ListVersionsResponseType listVersions(ListVersionsType request)
2704
 
        throws EucalyptusCloudException {
 
3070
                        throws EucalyptusCloudException {
2705
3071
                ListVersionsResponseType reply = (ListVersionsResponseType) request
2706
 
                .getReply();
 
3072
                                .getReply();
2707
3073
                String bucketName = request.getBucket();
2708
 
                String userId = request.getUserId();
 
3074
                Context ctx = Contexts.lookup();
 
3075
                Account account = ctx.getAccount();
2709
3076
                String prefix = request.getPrefix();
2710
3077
                if (prefix == null)
2711
3078
                        prefix = "";
2722
3089
 
2723
3090
                String delimiter = request.getDelimiter();
2724
3091
 
2725
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
3092
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
2726
3093
                BucketInfo bucketInfo = new BucketInfo(bucketName);
2727
3094
                bucketInfo.setHidden(false);
2728
3095
                List<BucketInfo> bucketList = db.query(bucketInfo);
2731
3098
 
2732
3099
                if (bucketList.size() > 0) {
2733
3100
                        BucketInfo bucket = bucketList.get(0);
2734
 
                        BucketLogData logData = bucket.getLoggingEnabled() ? request
2735
 
                                        .getLogData() : null;
2736
 
                                        if (bucket.canRead(userId)) {
2737
 
                                                if (bucket.isVersioningDisabled()) {
2738
 
                                                        db.rollback();
2739
 
                                                        throw new EucalyptusCloudException(
2740
 
                                                                        "Versioning has not been enabled for bucket: "
 
3101
                        BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
 
3102
                        if (ctx.hasAdministrativePrivileges() || (
 
3103
                                        bucket.canRead(account.getAccountNumber()) &&
 
3104
                                        (bucket.isGlobalRead() || Lookups.checkPrivilege(PolicySpec.S3_LISTBUCKETVERSIONS,
 
3105
                                                        PolicySpec.VENDOR_S3,
 
3106
                                                        PolicySpec.S3_RESOURCE_BUCKET,
 
3107
                                                        bucketName,
 
3108
                                                        null)))) {
 
3109
                                if (bucket.isVersioningDisabled()) {
 
3110
                                        db.rollback();
 
3111
                                        throw new EucalyptusCloudException(
 
3112
                                                        "Versioning has not been enabled for bucket: "
2741
3113
                                                                        + bucketName);
2742
 
                                                }
2743
 
                                                if (logData != null) {
2744
 
                                                        updateLogData(bucket, logData);
2745
 
                                                        reply.setLogData(logData);
2746
 
                                                }
2747
 
                                                if (request.isAdministrator()) {
2748
 
                                                        EntityWrapper<WalrusSnapshotInfo> dbSnap = db
 
3114
                                }
 
3115
                                if (logData != null) {
 
3116
                                        updateLogData(bucket, logData);
 
3117
                                        reply.setLogData(logData);
 
3118
                                }
 
3119
                                if (Contexts.lookup().hasAdministrativePrivileges()) {
 
3120
                                        EntityWrapper<WalrusSnapshotInfo> dbSnap = db
2749
3121
                                                        .recast(WalrusSnapshotInfo.class);
2750
 
                                                        WalrusSnapshotInfo walrusSnapInfo = new WalrusSnapshotInfo();
2751
 
                                                        walrusSnapInfo.setSnapshotBucket(bucketName);
2752
 
                                                        List<WalrusSnapshotInfo> walrusSnaps = dbSnap
 
3122
                                        WalrusSnapshotInfo walrusSnapInfo = new WalrusSnapshotInfo();
 
3123
                                        walrusSnapInfo.setSnapshotBucket(bucketName);
 
3124
                                        List<WalrusSnapshotInfo> walrusSnaps = dbSnap
2753
3125
                                                        .query(walrusSnapInfo);
2754
 
                                                        if (walrusSnaps.size() > 0) {
2755
 
                                                                db.rollback();
2756
 
                                                                throw new NoSuchBucketException(bucketName);
2757
 
                                                        }
2758
 
                                                }
2759
 
                                                reply.setName(bucketName);
2760
 
                                                reply.setIsTruncated(false);
2761
 
                                                if (maxKeys >= 0)
2762
 
                                                        reply.setMaxKeys(maxKeys);
2763
 
                                                reply.setPrefix(prefix);
2764
 
                                                reply.setKeyMarker(keyMarker);
2765
 
                                                reply.setVersionIdMarker(versionIdMarker);
2766
 
                                                if (delimiter != null)
2767
 
                                                        reply.setDelimiter(delimiter);
2768
 
                                                EntityWrapper<ObjectInfo> dbObject = db
 
3126
                                        if (walrusSnaps.size() > 0) {
 
3127
                                                db.rollback();
 
3128
                                                throw new NoSuchBucketException(bucketName);
 
3129
                                        }
 
3130
                                }
 
3131
                                reply.setName(bucketName);
 
3132
                                reply.setIsTruncated(false);
 
3133
                                if (maxKeys >= 0)
 
3134
                                        reply.setMaxKeys(maxKeys);
 
3135
                                reply.setPrefix(prefix);
 
3136
                                reply.setKeyMarker(keyMarker);
 
3137
                                reply.setVersionIdMarker(versionIdMarker);
 
3138
                                if (delimiter != null)
 
3139
                                        reply.setDelimiter(delimiter);
 
3140
                                EntityWrapper<ObjectInfo> dbObject = db
2769
3141
                                                .recast(ObjectInfo.class);
2770
 
                                                ObjectInfo searchObjectInfo = new ObjectInfo();
2771
 
                                                searchObjectInfo.setBucketName(bucketName);
2772
 
                                                List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
2773
 
                                                if (objectInfos.size() > 0) {
2774
 
                                                        int howManyProcessed = 0;
2775
 
                                                        if (keyMarker != null || objectInfos.size() < maxKeys)
2776
 
                                                                Collections.sort(objectInfos);
2777
 
                                                        ArrayList<VersionEntry> versions = new ArrayList<VersionEntry>();
2778
 
                                                        ArrayList<DeleteMarkerEntry> deleteMarkers = new ArrayList<DeleteMarkerEntry>();
2779
 
 
2780
 
                                                        for (ObjectInfo objectInfo : objectInfos) {
2781
 
                                                                String objectKey = objectInfo.getObjectKey();
2782
 
 
2783
 
                                                                if(keyMarker != null) { if(objectKey.compareTo(keyMarker)
2784
 
                                                                                <= 0) continue; } else if (versionIdMarker != null) {
2785
 
                                                                                        if(!objectInfo.getVersionId().equals(versionIdMarker))
2786
 
                                                                                                continue;
2787
 
                                                                                }
2788
 
 
2789
 
                                                                if (prefix != null) {
2790
 
                                                                        if (!objectKey.startsWith(prefix)) {
2791
 
                                                                                continue;
2792
 
                                                                        } else {
2793
 
                                                                                if (delimiter != null) {
2794
 
                                                                                        String[] parts = objectKey.substring(
2795
 
                                                                                                        prefix.length()).split(delimiter);
2796
 
                                                                                        if (parts.length > 1) {
2797
 
                                                                                                String prefixString = parts[0]
2798
 
                                                                                                                            + delimiter;
2799
 
                                                                                                boolean foundPrefix = false;
2800
 
                                                                                                for (PrefixEntry prefixEntry : prefixes) {
2801
 
                                                                                                        if (prefixEntry.getPrefix().equals(
2802
 
                                                                                                                        prefixString)) {
2803
 
                                                                                                                foundPrefix = true;
2804
 
                                                                                                                break;
2805
 
                                                                                                        }
2806
 
                                                                                                }
2807
 
                                                                                                if (!foundPrefix) {
2808
 
                                                                                                        prefixes.add(new PrefixEntry(
2809
 
                                                                                                                        prefixString));
2810
 
                                                                                                        if (maxKeys >= 0) {
2811
 
                                                                                                                if (howManyProcessed++ >= maxKeys) {
2812
 
                                                                                                                        reply.setIsTruncated(true);
2813
 
                                                                                                                        break;
2814
 
                                                                                                                }
2815
 
                                                                                                        }
2816
 
                                                                                                }
2817
 
                                                                                                continue;
2818
 
                                                                                        }
2819
 
                                                                                }
2820
 
                                                                        }
2821
 
                                                                }
2822
 
                                                                if (maxKeys >= 0) {
2823
 
                                                                        if (howManyProcessed++ >= maxKeys) {
2824
 
                                                                                reply.setIsTruncated(true);
2825
 
                                                                                break;
2826
 
                                                                        }
2827
 
                                                                }
2828
 
                                                                if (!objectInfo.getDeleted()) {
2829
 
                                                                        VersionEntry versionEntry = new VersionEntry();
2830
 
                                                                        versionEntry.setKey(objectKey);
2831
 
                                                                        versionEntry
2832
 
                                                                        .setVersionId(objectInfo.getVersionId());
2833
 
                                                                        versionEntry.setEtag(objectInfo.getEtag());
2834
 
                                                                        versionEntry.setLastModified(DateUtils.format(
2835
 
                                                                                        objectInfo.getLastModified().getTime(),
2836
 
                                                                                        DateUtils.ISO8601_DATETIME_PATTERN)
2837
 
                                                                                        + ".000Z");
2838
 
                                                                        String displayName = objectInfo.getOwnerId();
2839
 
                                                                        try {
2840
 
                                                                                User userInfo = Users.lookupUser(displayName);
2841
 
                                                                                versionEntry.setOwner(new CanonicalUserType(
2842
 
                                                                                                userInfo.getQueryId(), displayName));
2843
 
                                                                        } catch (NoSuchUserException e) {
2844
 
                                                                                db.rollback();
2845
 
                                                                                throw new AccessDeniedException("Bucket",
2846
 
                                                                                                bucketName, logData);
2847
 
                                                                        }
2848
 
                                                                        versionEntry.setSize(objectInfo.getSize());
2849
 
                                                                        versionEntry.setStorageClass(objectInfo
2850
 
                                                                                        .getStorageClass());
2851
 
                                                                        versionEntry.setIsLatest(objectInfo.getLast());
2852
 
                                                                        versions.add(versionEntry);
2853
 
                                                                } else {
2854
 
                                                                        DeleteMarkerEntry deleteMarkerEntry = new DeleteMarkerEntry();
2855
 
                                                                        deleteMarkerEntry.setKey(objectKey);
2856
 
                                                                        deleteMarkerEntry.setVersionId(objectInfo
2857
 
                                                                                        .getVersionId());
2858
 
                                                                        deleteMarkerEntry.setLastModified(DateUtils.format(
2859
 
                                                                                        objectInfo.getLastModified().getTime(),
2860
 
                                                                                        DateUtils.ISO8601_DATETIME_PATTERN)
2861
 
                                                                                        + ".000Z");
2862
 
                                                                        String displayName = objectInfo.getOwnerId();
2863
 
                                                                        try {
2864
 
                                                                                User userInfo = Users.lookupUser(displayName);
2865
 
                                                                                deleteMarkerEntry
2866
 
                                                                                .setOwner(new CanonicalUserType(
2867
 
                                                                                                userInfo.getQueryId(),
2868
 
                                                                                                displayName));
2869
 
                                                                        } catch (NoSuchUserException e) {
2870
 
                                                                                db.rollback();
2871
 
                                                                                throw new AccessDeniedException("Bucket",
2872
 
                                                                                                bucketName, logData);
2873
 
                                                                        }
2874
 
                                                                        deleteMarkerEntry.setIsLatest(objectInfo.getLast());
2875
 
                                                                        deleteMarkers.add(deleteMarkerEntry);
2876
 
                                                                }
2877
 
                                                        }
2878
 
                                                        reply.setVersions(versions);
2879
 
                                                        reply.setDeleteMarkers(deleteMarkers);
2880
 
                                                        if (prefix != null) {
2881
 
                                                                reply.setCommonPrefixes(prefixes);
2882
 
                                                        }
2883
 
                                                }
2884
 
                                        } else {
2885
 
                                                db.rollback();
2886
 
                                                throw new AccessDeniedException("Bucket", bucketName, logData);
2887
 
                                        }
 
3142
                                ObjectInfo searchObjectInfo = new ObjectInfo();
 
3143
                                searchObjectInfo.setBucketName(bucketName);
 
3144
                                List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
 
3145
                                if (objectInfos.size() > 0) {
 
3146
                                        int howManyProcessed = 0;
 
3147
                                        if (keyMarker != null || objectInfos.size() < maxKeys)
 
3148
                                                Collections.sort(objectInfos);
 
3149
                                        ArrayList<VersionEntry> versions = new ArrayList<VersionEntry>();
 
3150
                                        ArrayList<DeleteMarkerEntry> deleteMarkers = new ArrayList<DeleteMarkerEntry>();
 
3151
 
 
3152
                                        for (ObjectInfo objectInfo : objectInfos) {
 
3153
                                                String objectKey = objectInfo.getObjectKey();
 
3154
 
 
3155
                                                if(keyMarker != null) { if(objectKey.compareTo(keyMarker)
 
3156
                                                                <= 0) continue; } else if (versionIdMarker != null) {
 
3157
                                                                        if(!objectInfo.getVersionId().equals(versionIdMarker))
 
3158
                                                                                continue;
 
3159
                                                                }
 
3160
 
 
3161
                                                if (prefix != null) {
 
3162
                                                        if (!objectKey.startsWith(prefix)) {
 
3163
                                                                continue;
 
3164
                                                        } else {
 
3165
                                                                if (delimiter != null) {
 
3166
                                                                        String[] parts = objectKey.substring(
 
3167
                                                                                        prefix.length()).split(delimiter);
 
3168
                                                                        if (parts.length > 1) {
 
3169
                                                                                String prefixString = parts[0]
 
3170
                                                                                                + delimiter;
 
3171
                                                                                boolean foundPrefix = false;
 
3172
                                                                                for (PrefixEntry prefixEntry : prefixes) {
 
3173
                                                                                        if (prefixEntry.getPrefix().equals(
 
3174
                                                                                                        prefixString)) {
 
3175
                                                                                                foundPrefix = true;
 
3176
                                                                                                break;
 
3177
                                                                                        }
 
3178
                                                                                }
 
3179
                                                                                if (!foundPrefix) {
 
3180
                                                                                        prefixes.add(new PrefixEntry(
 
3181
                                                                                                        prefixString));
 
3182
                                                                                        if (maxKeys >= 0) {
 
3183
                                                                                                if (howManyProcessed++ >= maxKeys) {
 
3184
                                                                                                        reply.setIsTruncated(true);
 
3185
                                                                                                        break;
 
3186
                                                                                                }
 
3187
                                                                                        }
 
3188
                                                                                }
 
3189
                                                                                continue;
 
3190
                                                                        }
 
3191
                                                                }
 
3192
                                                        }
 
3193
                                                }
 
3194
                                                if (maxKeys >= 0) {
 
3195
                                                        if (howManyProcessed++ >= maxKeys) {
 
3196
                                                                reply.setIsTruncated(true);
 
3197
                                                                break;
 
3198
                                                        }
 
3199
                                                }
 
3200
                                                if (!objectInfo.getDeleted()) {
 
3201
                                                        VersionEntry versionEntry = new VersionEntry();
 
3202
                                                        versionEntry.setKey(objectKey);
 
3203
                                                        versionEntry
 
3204
                                                        .setVersionId(objectInfo.getVersionId());
 
3205
                                                        versionEntry.setEtag(objectInfo.getEtag());
 
3206
                                                        versionEntry.setLastModified(DateUtils.format(
 
3207
                                                                        objectInfo.getLastModified().getTime(),
 
3208
                                                                        DateUtils.ISO8601_DATETIME_PATTERN)
 
3209
                                                                        + ".000Z");
 
3210
                                                        // displayName is actually the owner account ID
 
3211
                                                        String displayName = objectInfo.getOwnerId();
 
3212
                                                        try {
 
3213
                                                                versionEntry.setOwner(new CanonicalUserType(Accounts.lookupAccountById(displayName).getName(), displayName));
 
3214
                                                        } catch (AuthException e) {
 
3215
                                                                db.rollback();
 
3216
                                                                throw new AccessDeniedException("Bucket",
 
3217
                                                                                bucketName, logData);
 
3218
                                                        }
 
3219
                                                        versionEntry.setSize(objectInfo.getSize());
 
3220
                                                        versionEntry.setStorageClass(objectInfo
 
3221
                                                                        .getStorageClass());
 
3222
                                                        versionEntry.setIsLatest(objectInfo.getLast());
 
3223
                                                        versions.add(versionEntry);
 
3224
                                                } else {
 
3225
                                                        DeleteMarkerEntry deleteMarkerEntry = new DeleteMarkerEntry();
 
3226
                                                        deleteMarkerEntry.setKey(objectKey);
 
3227
                                                        deleteMarkerEntry.setVersionId(objectInfo
 
3228
                                                                        .getVersionId());
 
3229
                                                        deleteMarkerEntry.setLastModified(DateUtils.format(
 
3230
                                                                        objectInfo.getLastModified().getTime(),
 
3231
                                                                        DateUtils.ISO8601_DATETIME_PATTERN)
 
3232
                                                                        + ".000Z");
 
3233
                                                        String displayName = objectInfo.getOwnerId();
 
3234
                                                        try {
 
3235
                                                                User userInfo = Accounts.lookupUserById(displayName);
 
3236
                                                                deleteMarkerEntry
 
3237
                                                                .setOwner(new CanonicalUserType(Accounts.getFirstActiveAccessKeyId( userInfo ),
 
3238
                                                                                displayName));
 
3239
                                                        } catch (AuthException e) {
 
3240
                                                                db.rollback();
 
3241
                                                                throw new AccessDeniedException("Bucket",
 
3242
                                                                                bucketName, logData);
 
3243
                                                        }
 
3244
                                                        deleteMarkerEntry.setIsLatest(objectInfo.getLast());
 
3245
                                                        deleteMarkers.add(deleteMarkerEntry);
 
3246
                                                }
 
3247
                                        }
 
3248
                                        reply.setVersions(versions);
 
3249
                                        reply.setDeleteMarkers(deleteMarkers);
 
3250
                                        if (prefix != null) {
 
3251
                                                reply.setCommonPrefixes(prefixes);
 
3252
                                        }
 
3253
                                }
 
3254
                        } else {
 
3255
                                db.rollback();
 
3256
                                throw new AccessDeniedException("Bucket", bucketName, logData);
 
3257
                        }
2888
3258
                } else {
2889
3259
                        db.rollback();
2890
3260
                        throw new NoSuchBucketException(bucketName);
2894
3264
        }
2895
3265
 
2896
3266
        public DeleteVersionResponseType deleteVersion(DeleteVersionType request)
2897
 
        throws EucalyptusCloudException {
 
3267
                        throws EucalyptusCloudException {
2898
3268
                DeleteVersionResponseType reply = (DeleteVersionResponseType) request
2899
 
                .getReply();
 
3269
                                .getReply();
2900
3270
                String bucketName = request.getBucket();
2901
3271
                String objectKey = request.getKey();
2902
 
                String userId = request.getUserId();
 
3272
                Context ctx = Contexts.lookup();
 
3273
                Account account = ctx.getAccount();
2903
3274
 
2904
 
                EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
 
3275
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
2905
3276
                BucketInfo bucketInfos = new BucketInfo(bucketName);
2906
3277
                List<BucketInfo> bucketList = db.query(bucketInfos);
2907
3278
 
2923
3294
                                        }
2924
3295
 
2925
3296
                                        if (foundObject != null) {
2926
 
                                                if (foundObject.canWrite(userId)) {
 
3297
                                                if (ctx.hasAdministrativePrivileges() || (
 
3298
                                                                Lookups.checkPrivilege(PolicySpec.S3_DELETEOBJECTVERSION,
 
3299
                                                                                PolicySpec.VENDOR_S3,
 
3300
                                                                                PolicySpec.S3_RESOURCE_OBJECT,
 
3301
                                                                                PolicySpec.objectFullName(bucketName, objectKey),
 
3302
                                                                                foundObject.getOwnerId()))) {
2927
3303
                                                        dbObject.delete(foundObject);
2928
3304
                                                        if(!foundObject.getDeleted()) {
2929
3305
                                                                String objectName = foundObject.getObjectName();                                                         
2930
3306
                                                                for (GrantInfo grantInfo : foundObject.getGrants()) {
2931
 
                                                                        db.getEntityManager().remove(grantInfo);
 
3307
                                                                        db.delete(grantInfo);
2932
3308
                                                                }
2933
3309
                                                                Long size = foundObject.getSize();
2934
 
                                                                bucketInfo.setBucketSize(bucketInfo.getBucketSize() - size);
 
3310
 
 
3311
                                                                boolean success = false;
 
3312
                                                                int retryCount = 0;
 
3313
                                                                do {
 
3314
                                                                        try {
 
3315
                                                                                decrementBucketSize(bucketName, size);
 
3316
                                                                                success = true;
 
3317
                                                                        } catch (NoSuchBucketException ex) {
 
3318
                                                                                db.rollback();
 
3319
                                                                                throw ex;
 
3320
                                                                        } catch (RollbackException ex) {
 
3321
                                                                                retryCount++;
 
3322
                                                                                LOG.trace("retrying update: " + bucketName);
 
3323
                                                                        } catch (EucalyptusCloudException ex) {
 
3324
                                                                                db.rollback();
 
3325
                                                                                throw ex;
 
3326
                                                                        }
 
3327
                                                                } while(!success && (retryCount < 5));
 
3328
 
2935
3329
                                                                ObjectDeleter objectDeleter = new ObjectDeleter(bucketName,
2936
 
                                                                                objectName, size);
2937
 
                                                                objectDeleter.start();
 
3330
                                                                                objectName, 
 
3331
                                                                                size, 
 
3332
                                                                                ctx.getUser().getName(),
 
3333
                                                                                ctx.getUser().getUserId(),
 
3334
                                                                                ctx.getAccount().getName(),
 
3335
                                                                                ctx.getAccount().getAccountNumber());
 
3336
                                                                Threads.lookup(Walrus.class, WalrusManager.ObjectDeleter.class).limitTo(10).submit(objectDeleter);
2938
3337
                                                        }
2939
3338
                                                        reply.setCode("200");
2940
3339
                                                        reply.setDescription("OK");
2957
3356
                db.commit();
2958
3357
                return reply;
2959
3358
        }
 
3359
 
 
3360
        public static InetAddress getBucketIp(String bucket) throws EucalyptusCloudException {
 
3361
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
 
3362
                try {
 
3363
                        BucketInfo searchBucket = new BucketInfo(bucket);
 
3364
                        db.getUnique(searchBucket);
 
3365
                        return WalrusProperties.getWalrusAddress();
 
3366
                } catch (EucalyptusCloudException ex) {
 
3367
                        throw ex;
 
3368
                } finally {
 
3369
                        db.rollback();
 
3370
                }
 
3371
        }
 
3372
 
 
3373
        public void fastDeleteObject(DeleteObjectType request) throws EucalyptusCloudException {
 
3374
                String bucketName = request.getBucket();
 
3375
                String objectKey = request.getKey();
 
3376
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
 
3377
                BucketInfo bucketInfos = new BucketInfo(bucketName);
 
3378
                List<BucketInfo> bucketList = db.query(bucketInfos);
 
3379
                if (bucketList.size() > 0) {
 
3380
                        BucketInfo bucketInfo = bucketList.get(0);
 
3381
                        BucketLogData logData = bucketInfo.getLoggingEnabled() ? request.getLogData() : null;
 
3382
                        ObjectInfo searchObjectInfo = new ObjectInfo(bucketName, objectKey);
 
3383
                        searchObjectInfo.setVersionId(WalrusProperties.NULL_VERSION_ID);
 
3384
                        EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
 
3385
                        List<ObjectInfo>objectInfos = dbObject.query(searchObjectInfo);
 
3386
                        if (objectInfos.size() > 0) {
 
3387
                                ObjectInfo foundObject = objectInfos.get(0);
 
3388
                                dbObject.delete(foundObject);
 
3389
                                String objectName = foundObject.getObjectName();
 
3390
                                for (GrantInfo grantInfo : foundObject.getGrants()) {
 
3391
                                        db.delete(grantInfo);
 
3392
                                }
 
3393
                                Long size = foundObject.getSize();
 
3394
                                try {
 
3395
                                        storageManager.deleteObject(bucketName, objectName);
 
3396
                                } catch (IOException ex) {
 
3397
                                        LOG.error(ex, ex);
 
3398
                                }                               boolean success = false;
 
3399
                                int retryCount = 0;
 
3400
                                do {
 
3401
                                        try {
 
3402
                                                decrementBucketSize(bucketName, size);
 
3403
                                                success = true;
 
3404
                                        } catch (NoSuchBucketException ex) {
 
3405
                                                db.rollback();
 
3406
                                                throw ex;
 
3407
                                        } catch (RollbackException ex) {
 
3408
                                                retryCount++;
 
3409
                                                LOG.trace("retrying update: " + bucketName);
 
3410
                                        } catch (EucalyptusCloudException ex) {
 
3411
                                                db.rollback();
 
3412
                                                throw ex;
 
3413
                                        }
 
3414
                                } while(!success && (retryCount < 5));
 
3415
 
 
3416
                        } else {
 
3417
                                db.rollback();
 
3418
                                throw new NoSuchEntityException(objectKey, logData);
 
3419
                        }
 
3420
                } else {
 
3421
                        db.rollback();
 
3422
                        throw new NoSuchBucketException(bucketName);
 
3423
                }
 
3424
                db.commit();
 
3425
        }
 
3426
 
 
3427
        public void fastDeleteBucket(DeleteBucketType request) throws EucalyptusCloudException {
 
3428
                String bucketName = request.getBucket();
 
3429
                EntityWrapper<BucketInfo> db = EntityWrapper.get(BucketInfo.class);
 
3430
                BucketInfo searchBucket = new BucketInfo(bucketName);
 
3431
                List<BucketInfo> bucketList = db.query(searchBucket);
 
3432
 
 
3433
                if (bucketList.size() > 0) {
 
3434
                        BucketInfo bucketFound = bucketList.get(0);
 
3435
                        EntityWrapper<ObjectInfo> dbObject = db
 
3436
                                        .recast(ObjectInfo.class);
 
3437
                        ObjectInfo searchObject = new ObjectInfo();
 
3438
                        searchObject.setBucketName(bucketName);
 
3439
                        searchObject.setDeleted(false);
 
3440
                        List<ObjectInfo> objectInfos = dbObject.query(searchObject);
 
3441
                        if (objectInfos.size() == 0) {
 
3442
                                db.delete(bucketFound);
 
3443
                                // Actually remove the bucket from the backing store
 
3444
                                try {
 
3445
                                        storageManager.deleteBucket(bucketName);
 
3446
                                        if (WalrusProperties.trackUsageStatistics)
 
3447
                                                walrusStatistics.decrementBucketCount();
 
3448
                                } catch (IOException ex) {
 
3449
                                        // set exception code in reply
 
3450
                                        LOG.error(ex);
 
3451
                                }
 
3452
                        } else {
 
3453
                                db.rollback();
 
3454
                                throw new BucketNotEmptyException(bucketName);
 
3455
                        }
 
3456
                } else {
 
3457
                        db.rollback();
 
3458
                        throw new NoSuchBucketException(bucketName);
 
3459
                }
 
3460
                db.commit();
 
3461
        }
2960
3462
}