diff --git a/swift/common/middleware/account_quotas.py b/swift/common/middleware/account_quotas.py index 917fd4f45b..87399af772 100644 --- a/swift/common/middleware/account_quotas.py +++ b/swift/common/middleware/account_quotas.py @@ -63,7 +63,7 @@ class AccountQuotaMiddleware(object): @wsgify def __call__(self, request): - if request.method not in ("POST", "PUT"): + if request.method not in ("POST", "PUT", "COPY"): return self.app try: @@ -98,7 +98,11 @@ class AccountQuotaMiddleware(object): if obj and request.method == "POST" or not obj: return self.app - copy_from = request.headers.get('X-Copy-From') + if request.method == 'COPY': + copy_from = container + '/' + obj + else: + copy_from = request.headers.get('X-Copy-From') + content_length = (request.content_length or 0) if obj and copy_from: diff --git a/test/unit/common/middleware/test_account_quotas.py b/test/unit/common/middleware/test_account_quotas.py index 9854fb605a..d24af41bfb 100644 --- a/test/unit/common/middleware/test_account_quotas.py +++ b/test/unit/common/middleware/test_account_quotas.py @@ -186,9 +186,23 @@ class TestAccountQuota(unittest.TestCase): res = req.get_response(app) self.assertEquals(res.status_int, 413) + def test_exceed_bytes_quota_copy_verb(self): + headers = [('x-account-bytes-used', '500'), + ('x-account-meta-quota-bytes', '1000'), + ('content-length', '1000')] + app = account_quotas.AccountQuotaMiddleware(FakeApp(headers)) + cache = FakeCache(None) + req = Request.blank('/v1/a/c2/o2', + environ={'REQUEST_METHOD': 'COPY', + 'swift.cache': cache}, + headers={'Destination': '/c/o'}) + res = req.get_response(app) + self.assertEquals(res.status_int, 413) + def test_not_exceed_bytes_quota_copy_from(self): headers = [('x-account-bytes-used', '0'), - ('x-account-meta-quota-bytes', '1000')] + ('x-account-meta-quota-bytes', '1000'), + ('content-length', '1000')] app = account_quotas.AccountQuotaMiddleware(FakeApp(headers)) cache = FakeCache(None) req = Request.blank('/v1/a/c/o', @@ -198,6 +212,19 @@ class TestAccountQuota(unittest.TestCase): res = req.get_response(app) self.assertEquals(res.status_int, 200) + def test_not_exceed_bytes_quota_copy_verb(self): + headers = [('x-account-bytes-used', '0'), + ('x-account-meta-quota-bytes', '1000'), + ('content-length', '1000')] + app = account_quotas.AccountQuotaMiddleware(FakeApp(headers)) + cache = FakeCache(None) + req = Request.blank('/v1/a/c2/o2', + environ={'REQUEST_METHOD': 'COPY', + 'swift.cache': cache}, + headers={'Destination': '/c/o'}) + res = req.get_response(app) + self.assertEquals(res.status_int, 200) + def test_quota_copy_from_no_src(self): headers = [('x-account-bytes-used', '0'), ('x-account-meta-quota-bytes', '1000')] @@ -223,8 +250,9 @@ class TestAccountQuota(unittest.TestCase): self.assertEquals(res.status_int, 200) def test_exceed_bytes_quota_reseller_copy_from(self): - headers = [('x-account-bytes-used', '1000'), - ('x-account-meta-quota-bytes', '0')] + headers = [('x-account-bytes-used', '500'), + ('x-account-meta-quota-bytes', '1000'), + ('content-length', '1000')] app = account_quotas.AccountQuotaMiddleware(FakeApp(headers)) cache = FakeCache(None) req = Request.blank('/v1/a/c/o', @@ -235,6 +263,20 @@ class TestAccountQuota(unittest.TestCase): res = req.get_response(app) self.assertEquals(res.status_int, 200) + def test_exceed_bytes_quota_reseller_copy_verb(self): + headers = [('x-account-bytes-used', '500'), + ('x-account-meta-quota-bytes', '1000'), + ('content-length', '1000')] + app = account_quotas.AccountQuotaMiddleware(FakeApp(headers)) + cache = FakeCache(None) + req = Request.blank('/v1/a/c2/o2', + environ={'REQUEST_METHOD': 'COPY', + 'swift.cache': cache, + 'reseller_request': True}, + headers={'Destination': 'c/o'}) + res = req.get_response(app) + self.assertEquals(res.status_int, 200) + def test_bad_application_quota(self): headers = [] app = account_quotas.AccountQuotaMiddleware(FakeBadApp(headers))