account_quota: migrate quota_bytes and quota_count to the sysmeta namespace
Account quota metadata such as quota_bytes and quota_count are stored in the `meta` namespace which users have access to. However, this should be only available to reseller admins. This patch adds support for writing the quota metadata to `sysmeta` namespace, so that it is not accessible by users. The account policy quota is already using `sysmeta` and has the namespace `X-Account-Quota-*`, so we are following this pattern. If present, `X-Account-Quota-Bytes` is always preferred. However, in order to maintain backwards compatibility, `X-Account-Meta-Quota-Bytes` will still be honoured if it exists and `X-Account-Quota-Bytes` is not present. This also adds some new "legacy" tests to validate backwards compatibility. Co-authored-by: Azmain Adib <adib1905@gmail.com> Co-authored-by: Daanish Khan <daanish1337@gmail.com> Co-authored-by: Mohammed Al-Jawaheri <mjawaheri02@gmail.com> Co-authored-by: Nada El-Mestkawy <nadamaged05@gmail.com> Co-authored-by: Tra Bui <trabui.0517@gmail.com> Co-authored-by: Chris Smart <distroguy@gmail.com> Change-Id: Icf7b26023ab5b84136ceaa103fa2797534320f1a
This commit is contained in:
parent
cd0fe25da1
commit
4eefae2482
@ -24,12 +24,22 @@ quota
|
|||||||
+---------------------------------------------+-------------------------------+
|
+---------------------------------------------+-------------------------------+
|
||||||
|Metadata | Use |
|
|Metadata | Use |
|
||||||
+=============================================+===============================+
|
+=============================================+===============================+
|
||||||
| X-Account-Meta-Quota-Bytes | Maximum overall bytes stored |
|
| X-Account-Meta-Quota-Bytes (obsoleted) | Maximum overall bytes stored |
|
||||||
| | in account across containers. |
|
| | in account across containers. |
|
||||||
+---------------------------------------------+-------------------------------+
|
+---------------------------------------------+-------------------------------+
|
||||||
| X-Account-Meta-Quota-Count | Maximum object count under |
|
| X-Account-Quota-Bytes | Maximum overall bytes stored |
|
||||||
|
| | in account across containers. |
|
||||||
|
+---------------------------------------------+-------------------------------+
|
||||||
|
| X-Account-Quota-Bytes-Policy-<policyname> | Maximum overall bytes stored |
|
||||||
|
| | in account across containers, |
|
||||||
|
| | for the given policy. |
|
||||||
|
+---------------------------------------------+-------------------------------+
|
||||||
|
| X-Account-Quota-Count | Maximum object count under |
|
||||||
| | account. |
|
| | account. |
|
||||||
+---------------------------------------------+-------------------------------+
|
+---------------------------------------------+-------------------------------+
|
||||||
|
| X-Account-Quota-Count-Policy-<policyname> | Maximum object count under |
|
||||||
|
| | account, for the given policy.|
|
||||||
|
+---------------------------------------------+-------------------------------+
|
||||||
|
|
||||||
|
|
||||||
Write requests to those metadata entries are only permitted for resellers.
|
Write requests to those metadata entries are only permitted for resellers.
|
||||||
@ -95,9 +105,9 @@ class AccountQuotaMiddleware(object):
|
|||||||
def validate_and_translate_quotas(self, request, quota_type):
|
def validate_and_translate_quotas(self, request, quota_type):
|
||||||
new_quotas = {}
|
new_quotas = {}
|
||||||
new_quotas[None] = request.headers.get(
|
new_quotas[None] = request.headers.get(
|
||||||
'X-Account-Meta-%s' % quota_type)
|
'X-Account-%s' % quota_type)
|
||||||
if request.headers.get(
|
if request.headers.get(
|
||||||
'X-Remove-Account-Meta-%s' % quota_type):
|
'X-Remove-Account-%s' % quota_type):
|
||||||
new_quotas[None] = '' # X-Remove dominates if both are present
|
new_quotas[None] = '' # X-Remove dominates if both are present
|
||||||
|
|
||||||
for policy in POLICIES:
|
for policy in POLICIES:
|
||||||
@ -114,8 +124,9 @@ class AccountQuotaMiddleware(object):
|
|||||||
raise HTTPBadRequest()
|
raise HTTPBadRequest()
|
||||||
for idx, quota in new_quotas.items():
|
for idx, quota in new_quotas.items():
|
||||||
if idx is None:
|
if idx is None:
|
||||||
continue # For legacy reasons, it's in user meta
|
hdr = 'X-Account-Sysmeta-%s' % quota_type
|
||||||
hdr = 'X-Account-Sysmeta-%s-Policy-%d' % (quota_type, idx)
|
else:
|
||||||
|
hdr = 'X-Account-Sysmeta-%s-Policy-%d' % (quota_type, idx)
|
||||||
request.headers[hdr] = quota
|
request.headers[hdr] = quota
|
||||||
elif any(quota is not None for quota in new_quotas.values()):
|
elif any(quota is not None for quota in new_quotas.values()):
|
||||||
# deny quota set for non-reseller
|
# deny quota set for non-reseller
|
||||||
@ -123,11 +134,29 @@ class AccountQuotaMiddleware(object):
|
|||||||
|
|
||||||
def handle_account(self, request):
|
def handle_account(self, request):
|
||||||
if request.method in ("POST", "PUT"):
|
if request.method in ("POST", "PUT"):
|
||||||
|
# Support old meta format
|
||||||
|
for legacy_header in [
|
||||||
|
'X-Account-Meta-Quota-Bytes',
|
||||||
|
'X-Remove-Account-Meta-Quota-Bytes',
|
||||||
|
]:
|
||||||
|
new_header = legacy_header.replace('-Meta-', '-')
|
||||||
|
legacy_value = request.headers.get(legacy_header)
|
||||||
|
if legacy_value is not None and not \
|
||||||
|
request.headers.get(new_header):
|
||||||
|
request.headers[new_header] = legacy_value
|
||||||
# account request, so we pay attention to the quotas
|
# account request, so we pay attention to the quotas
|
||||||
self.validate_and_translate_quotas(request, "Quota-Bytes")
|
self.validate_and_translate_quotas(request, "Quota-Bytes")
|
||||||
self.validate_and_translate_quotas(request, "Quota-Count")
|
self.validate_and_translate_quotas(request, "Quota-Count")
|
||||||
resp = request.get_response(self.app)
|
resp = request.get_response(self.app)
|
||||||
# Non-resellers can't update quotas, but they *can* see them
|
# Non-resellers can't update quotas, but they *can* see them
|
||||||
|
# Global quotas
|
||||||
|
postfixes = ('Quota-Bytes', 'Quota-Count')
|
||||||
|
for postfix in postfixes:
|
||||||
|
value = resp.headers.get('X-Account-Sysmeta-%s' % postfix)
|
||||||
|
if value:
|
||||||
|
resp.headers['X-Account-%s' % postfix] = value
|
||||||
|
|
||||||
|
# Per policy quotas
|
||||||
for policy in POLICIES:
|
for policy in POLICIES:
|
||||||
infixes = ('Quota-Bytes-Policy', 'Quota-Count-Policy')
|
infixes = ('Quota-Bytes-Policy', 'Quota-Count-Policy')
|
||||||
for infix in infixes:
|
for infix in infixes:
|
||||||
@ -170,7 +199,11 @@ class AccountQuotaMiddleware(object):
|
|||||||
|
|
||||||
# Check for quota byte violation
|
# Check for quota byte violation
|
||||||
try:
|
try:
|
||||||
quota = int(account_info['meta'].get('quota-bytes', -1))
|
quota = int(
|
||||||
|
account_info["sysmeta"].get(
|
||||||
|
"quota-bytes", account_info["meta"].get("quota-bytes", -1)
|
||||||
|
)
|
||||||
|
)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
quota = -1
|
quota = -1
|
||||||
if quota >= 0:
|
if quota >= 0:
|
||||||
@ -191,7 +224,7 @@ class AccountQuotaMiddleware(object):
|
|||||||
|
|
||||||
# Check for quota count violation
|
# Check for quota count violation
|
||||||
try:
|
try:
|
||||||
quota = int(account_info['meta'].get('quota-count', -1))
|
quota = int(account_info['sysmeta'].get('quota-count', -1))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
quota = -1
|
quota = -1
|
||||||
if quota >= 0:
|
if quota >= 0:
|
||||||
|
@ -968,10 +968,9 @@ class TestAccountQuotas(unittest.TestCase):
|
|||||||
resp.read()
|
resp.read()
|
||||||
self.assertEqual(resp.status, 204)
|
self.assertEqual(resp.status, 204)
|
||||||
|
|
||||||
def test_admin_can_set_and_remove_user_quota(self):
|
def _test_admin_can_set_and_remove_user_quota(self, quota_header):
|
||||||
if tf.skip_if_no_reseller_admin:
|
if tf.skip_if_no_reseller_admin:
|
||||||
raise SkipTest('No admin user configured')
|
raise SkipTest('No admin user configured')
|
||||||
quota_header = 'X-Account-Meta-Quota-Bytes'
|
|
||||||
|
|
||||||
def get_current_quota():
|
def get_current_quota():
|
||||||
def head(url, token, parsed, conn):
|
def head(url, token, parsed, conn):
|
||||||
@ -984,7 +983,9 @@ class TestAccountQuotas(unittest.TestCase):
|
|||||||
resp = retry(head)
|
resp = retry(head)
|
||||||
resp.read()
|
resp.read()
|
||||||
self.assertEqual(resp.status, 204)
|
self.assertEqual(resp.status, 204)
|
||||||
return resp.headers.get(quota_header)
|
# Non-user-meta is authoritative now
|
||||||
|
return resp.headers.get(quota_header.replace('-Meta-', '-'),
|
||||||
|
resp.headers.get(quota_header))
|
||||||
|
|
||||||
original_quota = get_current_quota()
|
original_quota = get_current_quota()
|
||||||
|
|
||||||
@ -1008,6 +1009,14 @@ class TestAccountQuotas(unittest.TestCase):
|
|||||||
finally:
|
finally:
|
||||||
self._check_admin_can_post({quota_header: original_quota or ''})
|
self._check_admin_can_post({quota_header: original_quota or ''})
|
||||||
|
|
||||||
|
def test_admin_can_set_and_remove_user_quota_legacy(self):
|
||||||
|
self._test_admin_can_set_and_remove_user_quota(
|
||||||
|
'X-Account-Meta-Quota-Bytes')
|
||||||
|
|
||||||
|
def test_admin_can_set_and_remove_user_quota(self):
|
||||||
|
self._test_admin_can_set_and_remove_user_quota(
|
||||||
|
'X-Account-Quota-Bytes')
|
||||||
|
|
||||||
def test_admin_can_set_and_remove_user_policy_quota(self):
|
def test_admin_can_set_and_remove_user_policy_quota(self):
|
||||||
if tf.skip_if_no_reseller_admin:
|
if tf.skip_if_no_reseller_admin:
|
||||||
raise SkipTest('No admin user configured')
|
raise SkipTest('No admin user configured')
|
||||||
|
@ -109,7 +109,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
# activation of the account-quota middleware
|
# activation of the account-quota middleware
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '1000',
|
'x-account-bytes-used': '1000',
|
||||||
'x-account-meta-quota-bytes': 'pasty-plastogene'})
|
'x-account-sysmeta-quota-bytes': 'pasty-plastogene'})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o',
|
req = Request.blank('/v1/a/c/o',
|
||||||
@ -118,7 +118,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
|
|
||||||
def test_exceed_bytes_quota(self):
|
def test_exceed_bytes_quota_legacy(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '1000',
|
'x-account-bytes-used': '1000',
|
||||||
'x-account-meta-quota-bytes': '0'})
|
'x-account-meta-quota-bytes': '0'})
|
||||||
@ -131,13 +131,26 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
self.assertEqual(res.status_int, 413)
|
self.assertEqual(res.status_int, 413)
|
||||||
self.assertEqual(res.body, b'Upload exceeds quota.')
|
self.assertEqual(res.body, b'Upload exceeds quota.')
|
||||||
|
|
||||||
|
def test_exceed_bytes_quota(self):
|
||||||
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
|
'x-account-bytes-used': '1000',
|
||||||
|
'x-account-sysmeta-quota-bytes': '0'})
|
||||||
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
|
cache = FakeCache(None)
|
||||||
|
req = Request.blank('/v1/a/c/o',
|
||||||
|
environ={'REQUEST_METHOD': 'PUT',
|
||||||
|
'swift.cache': cache})
|
||||||
|
res = req.get_response(app)
|
||||||
|
self.assertEqual(res.status_int, 413)
|
||||||
|
self.assertEqual(res.body, b'Upload exceeds quota.')
|
||||||
|
|
||||||
@patch_policies
|
@patch_policies
|
||||||
def test_exceed_per_policy_quota(self):
|
def test_exceed_per_policy_quota(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '100',
|
'x-account-bytes-used': '100',
|
||||||
'x-account-storage-policy-unu-bytes-used': '100',
|
'x-account-storage-policy-unu-bytes-used': '100',
|
||||||
'x-account-sysmeta-quota-bytes-policy-1': '10',
|
'x-account-sysmeta-quota-bytes-policy-1': '10',
|
||||||
'x-account-meta-quota-bytes': '1000'})
|
'x-account-sysmeta-quota-bytes': '1000'})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o',
|
req = Request.blank('/v1/a/c/o',
|
||||||
@ -148,13 +161,15 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
self.assertEqual(res.body, b'Upload exceeds policy quota.')
|
self.assertEqual(res.body, b'Upload exceeds policy quota.')
|
||||||
|
|
||||||
@patch_policies
|
@patch_policies
|
||||||
def test_policy_quota_translation(self):
|
def test_policy_quota_translation_legacy_loses(self):
|
||||||
|
# if we have both meta (legacy) and sysmeta, ensure sysmeta wins
|
||||||
def do_test(method):
|
def do_test(method):
|
||||||
self.app.register(method, '/v1/a', HTTPOk, {
|
self.app.register(method, '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '100',
|
'x-account-bytes-used': '100',
|
||||||
'x-account-storage-policy-unu-bytes-used': '100',
|
'x-account-storage-policy-unu-bytes-used': '100',
|
||||||
'x-account-sysmeta-quota-bytes-policy-1': '10',
|
'x-account-sysmeta-quota-bytes-policy-1': '10',
|
||||||
'x-account-meta-quota-bytes': '1000'})
|
'x-account-sysmeta-quota-bytes': '1000',
|
||||||
|
'x-account-meta-quota-bytes': '2000'})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a', method=method, environ={
|
req = Request.blank('/v1/a', method=method, environ={
|
||||||
@ -162,7 +177,37 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
self.assertEqual(res.headers.get(
|
self.assertEqual(res.headers.get(
|
||||||
'X-Account-Meta-Quota-Bytes'), '1000')
|
'X-Account-Quota-Bytes'), '1000')
|
||||||
|
self.assertEqual(res.headers.get(
|
||||||
|
'X-Account-Meta-Quota-Bytes'), '2000')
|
||||||
|
self.assertEqual(res.headers.get(
|
||||||
|
'X-Account-Sysmeta-Quota-Bytes-Policy-1'), '10')
|
||||||
|
self.assertEqual(res.headers.get(
|
||||||
|
'X-Account-Quota-Bytes-Policy-Unu'), '10')
|
||||||
|
self.assertEqual(res.headers.get(
|
||||||
|
'X-Account-Storage-Policy-Unu-Bytes-Used'), '100')
|
||||||
|
|
||||||
|
do_test('GET')
|
||||||
|
do_test('HEAD')
|
||||||
|
|
||||||
|
@patch_policies
|
||||||
|
def test_policy_quota_translation(self):
|
||||||
|
def do_test(method):
|
||||||
|
self.app.register(method, '/v1/a', HTTPOk, {
|
||||||
|
'x-account-bytes-used': '100',
|
||||||
|
'x-account-storage-policy-unu-bytes-used': '100',
|
||||||
|
'x-account-sysmeta-quota-bytes-policy-1': '10',
|
||||||
|
'x-account-sysmeta-quota-bytes': '1000'})
|
||||||
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
|
cache = FakeCache(None)
|
||||||
|
req = Request.blank('/v1/a', method=method, environ={
|
||||||
|
'swift.cache': cache})
|
||||||
|
res = req.get_response(app)
|
||||||
|
self.assertEqual(res.status_int, 200)
|
||||||
|
self.assertEqual(res.headers.get(
|
||||||
|
'X-Account-Sysmeta-Quota-Bytes'), '1000')
|
||||||
|
self.assertEqual(res.headers.get(
|
||||||
|
'X-Account-Quota-Bytes'), '1000')
|
||||||
self.assertEqual(res.headers.get(
|
self.assertEqual(res.headers.get(
|
||||||
'X-Account-Sysmeta-Quota-Bytes-Policy-1'), '10')
|
'X-Account-Sysmeta-Quota-Bytes-Policy-1'), '10')
|
||||||
self.assertEqual(res.headers.get(
|
self.assertEqual(res.headers.get(
|
||||||
@ -176,7 +221,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_exceed_quota_not_authorized(self):
|
def test_exceed_quota_not_authorized(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '1000',
|
'x-account-bytes-used': '1000',
|
||||||
'x-account-meta-quota-bytes': '0'})
|
'x-account-sysmeta-quota-bytes': '0'})
|
||||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o', method='PUT',
|
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||||
@ -185,7 +230,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 403)
|
self.assertEqual(res.status_int, 403)
|
||||||
|
|
||||||
def test_exceed_quota_authorized(self):
|
def test_exceed_quota_authorized_legacy(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '1000',
|
'x-account-bytes-used': '1000',
|
||||||
'x-account-meta-quota-bytes': '0'})
|
'x-account-meta-quota-bytes': '0'})
|
||||||
@ -197,10 +242,22 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 413)
|
self.assertEqual(res.status_int, 413)
|
||||||
|
|
||||||
|
def test_exceed_quota_authorized(self):
|
||||||
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
|
'x-account-bytes-used': '1000',
|
||||||
|
'x-account-sysmeta-quota-bytes': '0'})
|
||||||
|
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||||
|
cache = FakeCache(None)
|
||||||
|
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||||
|
headers={'x-auth-token': 'secret'},
|
||||||
|
environ={'swift.cache': cache})
|
||||||
|
res = req.get_response(app)
|
||||||
|
self.assertEqual(res.status_int, 413)
|
||||||
|
|
||||||
def test_under_quota_not_authorized(self):
|
def test_under_quota_not_authorized(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '0',
|
'x-account-bytes-used': '0',
|
||||||
'x-account-meta-quota-bytes': '1000'})
|
'x-account-sysmeta-quota-bytes': '1000'})
|
||||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o', method='PUT',
|
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||||
@ -209,7 +266,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 403)
|
self.assertEqual(res.status_int, 403)
|
||||||
|
|
||||||
def test_under_quota_authorized(self):
|
def test_under_quota_authorized_legacy(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '0',
|
'x-account-bytes-used': '0',
|
||||||
'x-account-meta-quota-bytes': '1000'})
|
'x-account-meta-quota-bytes': '1000'})
|
||||||
@ -221,10 +278,22 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
|
|
||||||
def test_exceed_quota_bytes_on_empty_account_not_authorized(self):
|
def test_under_quota_authorized(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '0',
|
'x-account-bytes-used': '0',
|
||||||
'x-account-meta-quota-bytes': '10'})
|
'x-account-sysmeta-quota-bytes': '1000'})
|
||||||
|
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||||
|
cache = FakeCache(None)
|
||||||
|
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||||
|
headers={'x-auth-token': 'secret'},
|
||||||
|
environ={'swift.cache': cache})
|
||||||
|
res = req.get_response(app)
|
||||||
|
self.assertEqual(res.status_int, 200)
|
||||||
|
|
||||||
|
def test_exceed_quota_bytes_on_empty_account_authorized(self):
|
||||||
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
|
'x-account-bytes-used': '0',
|
||||||
|
'x-account-sysmeta-quota-bytes': '10'})
|
||||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o', method='PUT',
|
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||||
@ -235,10 +304,10 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
self.assertEqual(res.status_int, 413)
|
self.assertEqual(res.status_int, 413)
|
||||||
self.assertEqual(res.body, b'Upload exceeds quota.')
|
self.assertEqual(res.body, b'Upload exceeds quota.')
|
||||||
|
|
||||||
def test_exceed_quota_bytes_not_authorized(self):
|
def test_exceed_quota_bytes_authorized(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '100',
|
'x-account-bytes-used': '100',
|
||||||
'x-account-meta-quota-bytes': '1000'})
|
'x-account-sysmeta-quota-bytes': '1000'})
|
||||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o', method='PUT',
|
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||||
@ -252,7 +321,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_over_quota_container_create_still_works(self):
|
def test_over_quota_container_create_still_works(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '1001',
|
'x-account-bytes-used': '1001',
|
||||||
'x-account-meta-quota-bytes': '1000'})
|
'x-account-sysmeta-quota-bytes': '1000'})
|
||||||
self.app.register('PUT', '/v1/a/new_container', HTTPOk, {})
|
self.app.register('PUT', '/v1/a/new_container', HTTPOk, {})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
@ -266,7 +335,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_over_quota_container_post_still_works(self):
|
def test_over_quota_container_post_still_works(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '1001',
|
'x-account-bytes-used': '1001',
|
||||||
'x-account-meta-quota-bytes': '1000'})
|
'x-account-sysmeta-quota-bytes': '1000'})
|
||||||
self.app.register('POST', '/v1/a/new_container', HTTPOk, {})
|
self.app.register('POST', '/v1/a/new_container', HTTPOk, {})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
@ -280,7 +349,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_over_quota_obj_post_still_works(self):
|
def test_over_quota_obj_post_still_works(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '1001',
|
'x-account-bytes-used': '1001',
|
||||||
'x-account-meta-quota-bytes': '1000'})
|
'x-account-sysmeta-quota-bytes': '1000'})
|
||||||
self.app.register('POST', '/v1/a/c/o', HTTPOk, {})
|
self.app.register('POST', '/v1/a/c/o', HTTPOk, {})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
@ -294,7 +363,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_exceed_bytes_quota_reseller(self):
|
def test_exceed_bytes_quota_reseller(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '1000',
|
'x-account-bytes-used': '1000',
|
||||||
'x-account-meta-quota-bytes': '0'})
|
'x-account-sysmeta-quota-bytes': '0'})
|
||||||
self.app.register('PUT', '/v1/a', HTTPOk, {})
|
self.app.register('PUT', '/v1/a', HTTPOk, {})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
@ -308,7 +377,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_exceed_bytes_quota_reseller_copy_from(self):
|
def test_exceed_bytes_quota_reseller_copy_from(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '500',
|
'x-account-bytes-used': '500',
|
||||||
'x-account-meta-quota-bytes': '1000'})
|
'x-account-sysmeta-quota-bytes': '1000'})
|
||||||
self.app.register('GET', '/v1/a/c2/o2', HTTPOk, {
|
self.app.register('GET', '/v1/a/c2/o2', HTTPOk, {
|
||||||
'content-length': '1000'}, b'a' * 1000)
|
'content-length': '1000'}, b'a' * 1000)
|
||||||
app = copy.filter_factory({})(
|
app = copy.filter_factory({})(
|
||||||
@ -325,7 +394,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_exceed_bytes_quota_reseller_copy_verb(self):
|
def test_exceed_bytes_quota_reseller_copy_verb(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '500',
|
'x-account-bytes-used': '500',
|
||||||
'x-account-meta-quota-bytes': '1000'})
|
'x-account-sysmeta-quota-bytes': '1000'})
|
||||||
self.app.register('GET', '/v1/a/c2/o2', HTTPOk, {
|
self.app.register('GET', '/v1/a/c2/o2', HTTPOk, {
|
||||||
'content-length': '1000'}, b'a' * 1000)
|
'content-length': '1000'}, b'a' * 1000)
|
||||||
app = copy.filter_factory({})(
|
app = copy.filter_factory({})(
|
||||||
@ -361,7 +430,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_not_exceed_bytes_quota(self):
|
def test_not_exceed_bytes_quota(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-bytes-used': '1000',
|
'x-account-bytes-used': '1000',
|
||||||
'x-account-meta-quota-bytes': '2000'})
|
'x-account-sysmeta-quota-bytes': '2000'})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o',
|
req = Request.blank('/v1/a/c/o',
|
||||||
@ -376,7 +445,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
req = Request.blank('/v1/a',
|
req = Request.blank('/v1/a',
|
||||||
environ={'REQUEST_METHOD': 'POST',
|
environ={'REQUEST_METHOD': 'POST',
|
||||||
'swift.cache': cache,
|
'swift.cache': cache,
|
||||||
'HTTP_X_ACCOUNT_META_QUOTA_BYTES': 'abc',
|
'HTTP_X_ACCOUNT_QUOTA_BYTES': 'abc',
|
||||||
'reseller_request': True})
|
'reseller_request': True})
|
||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 400)
|
self.assertEqual(res.status_int, 400)
|
||||||
@ -395,13 +464,13 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
self.assertEqual(res.status_int, 400)
|
self.assertEqual(res.status_int, 400)
|
||||||
self.assertEqual(self.app.calls, [])
|
self.assertEqual(self.app.calls, [])
|
||||||
|
|
||||||
def test_valid_quotas_admin(self):
|
def test_valid_quotas_non_admin_fails(self):
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a',
|
req = Request.blank('/v1/a',
|
||||||
environ={'REQUEST_METHOD': 'POST',
|
environ={'REQUEST_METHOD': 'POST',
|
||||||
'swift.cache': cache,
|
'swift.cache': cache,
|
||||||
'HTTP_X_ACCOUNT_META_QUOTA_BYTES': '100'})
|
'HTTP_X_ACCOUNT_QUOTA_BYTES': '100'})
|
||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 403)
|
self.assertEqual(res.status_int, 403)
|
||||||
self.assertEqual(self.app.calls, [])
|
self.assertEqual(self.app.calls, [])
|
||||||
@ -418,7 +487,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
self.assertEqual(res.status_int, 403)
|
self.assertEqual(res.status_int, 403)
|
||||||
self.assertEqual(self.app.calls, [])
|
self.assertEqual(self.app.calls, [])
|
||||||
|
|
||||||
def test_valid_quotas_reseller(self):
|
def test_valid_quotas_reseller_legacy(self):
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a',
|
req = Request.blank('/v1/a',
|
||||||
@ -430,7 +499,42 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
self.assertEqual(self.app.calls_with_headers, [
|
self.assertEqual(self.app.calls_with_headers, [
|
||||||
('POST', '/v1/a', {'Host': 'localhost:80',
|
('POST', '/v1/a', {'Host': 'localhost:80',
|
||||||
'X-Account-Meta-Quota-Bytes': '100'})])
|
'X-Account-Quota-Bytes': '100',
|
||||||
|
'X-Account-Meta-Quota-Bytes': '100',
|
||||||
|
'X-Account-Sysmeta-Quota-Bytes': '100'})])
|
||||||
|
|
||||||
|
def test_valid_quotas_reseller_legacy_loses(self):
|
||||||
|
# if we have both meta (legacy) and sysmeta, ensure sysmeta wins
|
||||||
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
|
cache = FakeCache(None)
|
||||||
|
req = Request.blank('/v1/a',
|
||||||
|
environ={'REQUEST_METHOD': 'POST',
|
||||||
|
'swift.cache': cache,
|
||||||
|
'HTTP_X_ACCOUNT_QUOTA_BYTES': '100',
|
||||||
|
'HTTP_X_ACCOUNT_META_QUOTA_BYTES': '200',
|
||||||
|
'reseller_request': True})
|
||||||
|
res = req.get_response(app)
|
||||||
|
self.assertEqual(res.status_int, 200)
|
||||||
|
self.assertEqual(self.app.calls_with_headers, [
|
||||||
|
('POST', '/v1/a', {'Host': 'localhost:80',
|
||||||
|
'X-Account-Quota-Bytes': '100',
|
||||||
|
'X-Account-Meta-Quota-Bytes': '200',
|
||||||
|
'X-Account-Sysmeta-Quota-Bytes': '100'})])
|
||||||
|
|
||||||
|
def test_valid_quotas_reseller(self):
|
||||||
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
|
cache = FakeCache(None)
|
||||||
|
req = Request.blank('/v1/a',
|
||||||
|
environ={'REQUEST_METHOD': 'POST',
|
||||||
|
'swift.cache': cache,
|
||||||
|
'HTTP_X_ACCOUNT_QUOTA_BYTES': '100',
|
||||||
|
'reseller_request': True})
|
||||||
|
res = req.get_response(app)
|
||||||
|
self.assertEqual(res.status_int, 200)
|
||||||
|
self.assertEqual(self.app.calls_with_headers, [
|
||||||
|
('POST', '/v1/a', {'Host': 'localhost:80',
|
||||||
|
'X-Account-Quota-Bytes': '100',
|
||||||
|
'X-Account-Sysmeta-Quota-Bytes': '100'})])
|
||||||
|
|
||||||
@patch_policies
|
@patch_policies
|
||||||
def test_valid_policy_quota_reseller(self):
|
def test_valid_policy_quota_reseller(self):
|
||||||
@ -454,7 +558,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
req = Request.blank('/v1/a',
|
req = Request.blank('/v1/a',
|
||||||
environ={'REQUEST_METHOD': 'POST',
|
environ={'REQUEST_METHOD': 'POST',
|
||||||
'swift.cache': cache,
|
'swift.cache': cache,
|
||||||
'HTTP_X_ACCOUNT_META_QUOTA_BYTES': ''})
|
'HTTP_X_ACCOUNT_QUOTA_BYTES': ''})
|
||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 403)
|
self.assertEqual(res.status_int, 403)
|
||||||
|
|
||||||
@ -464,7 +568,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
req = Request.blank('/v1/a', environ={
|
req = Request.blank('/v1/a', environ={
|
||||||
'REQUEST_METHOD': 'POST',
|
'REQUEST_METHOD': 'POST',
|
||||||
'swift.cache': cache,
|
'swift.cache': cache,
|
||||||
'HTTP_X_REMOVE_ACCOUNT_META_QUOTA_BYTES': 'True'})
|
'HTTP_X_REMOVE_ACCOUNT_QUOTA_BYTES': 'True'})
|
||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 403)
|
self.assertEqual(res.status_int, 403)
|
||||||
|
|
||||||
@ -472,7 +576,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
req = Request.blank('/v1/a',
|
req = Request.blank('/v1/a',
|
||||||
environ={'REQUEST_METHOD': 'POST',
|
environ={'REQUEST_METHOD': 'POST',
|
||||||
'HTTP_X_ACCOUNT_META_QUOTA_BYTES': '',
|
'HTTP_X_ACCOUNT_QUOTA_BYTES': '',
|
||||||
'reseller_request': True})
|
'reseller_request': True})
|
||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
@ -483,7 +587,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
req = Request.blank('/v1/a', environ={
|
req = Request.blank('/v1/a', environ={
|
||||||
'REQUEST_METHOD': 'POST',
|
'REQUEST_METHOD': 'POST',
|
||||||
'swift.cache': cache,
|
'swift.cache': cache,
|
||||||
'HTTP_X_REMOVE_ACCOUNT_META_QUOTA_BYTES': 'True',
|
'HTTP_X_REMOVE_ACCOUNT_QUOTA_BYTES': 'True',
|
||||||
'reseller_request': True})
|
'reseller_request': True})
|
||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
@ -541,7 +645,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_exceed_count_quota(self):
|
def test_exceed_count_quota(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-object-count': '10',
|
'x-account-object-count': '10',
|
||||||
'x-account-meta-quota-count': '10'})
|
'x-account-sysmeta-quota-count': '10'})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o',
|
req = Request.blank('/v1/a/c/o',
|
||||||
@ -553,7 +657,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
|
|
||||||
def test_exceed_quota_count_not_authorized(self):
|
def test_exceed_quota_count_not_authorized(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-meta-quota-count': '0'})
|
'x-account-sysmeta-quota-count': '0'})
|
||||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o', method='PUT',
|
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||||
@ -564,7 +668,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
|
|
||||||
def test_exceed_count_quota_authorized(self):
|
def test_exceed_count_quota_authorized(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-meta-quota-count': '0'})
|
'x-account-sysmeta-quota-count': '0'})
|
||||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o', method='PUT',
|
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||||
@ -576,7 +680,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_under_quota_count_not_authorized(self):
|
def test_under_quota_count_not_authorized(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-object-count': '0',
|
'x-account-object-count': '0',
|
||||||
'x-account-meta-quota-count': '5'})
|
'x-account-sysmeta-quota-count': '5'})
|
||||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o', method='PUT',
|
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||||
@ -588,7 +692,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_under_quota_count_authorized(self):
|
def test_under_quota_count_authorized(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-object-count': '0',
|
'x-account-object-count': '0',
|
||||||
'x-account-meta-quota-count': '5'})
|
'x-account-sysmeta-quota-count': '5'})
|
||||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o', method='PUT',
|
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||||
@ -600,7 +704,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_exceed_quota_count_on_empty_account_not_authorized(self):
|
def test_exceed_quota_count_on_empty_account_not_authorized(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-object-count': '0',
|
'x-account-object-count': '0',
|
||||||
'x-account-meta-quota-count': '0'})
|
'x-account-sysmeta-quota-count': '0'})
|
||||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o', method='PUT',
|
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||||
@ -612,7 +716,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_exceed_quota_count_authorized(self):
|
def test_exceed_quota_count_authorized(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-object-count': '5',
|
'x-account-object-count': '5',
|
||||||
'x-account-meta-quota-count': '5'})
|
'x-account-sysmeta-quota-count': '5'})
|
||||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o', method='PUT',
|
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||||
@ -625,7 +729,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_over_quota_count_container_create_still_works(self):
|
def test_over_quota_count_container_create_still_works(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-object-count': '6',
|
'x-account-object-count': '6',
|
||||||
'x-account-meta-quota-count': '5'})
|
'x-account-sysmeta-quota-count': '5'})
|
||||||
self.app.register('PUT', '/v1/a/new_container', HTTPOk, {})
|
self.app.register('PUT', '/v1/a/new_container', HTTPOk, {})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
@ -639,7 +743,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_over_quota_count_container_post_still_works(self):
|
def test_over_quota_count_container_post_still_works(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-quota-count': '6',
|
'x-account-quota-count': '6',
|
||||||
'x-account-meta-quota-count': '5'})
|
'x-account-sysmeta-quota-count': '5'})
|
||||||
self.app.register('POST', '/v1/a/new_container', HTTPOk, {})
|
self.app.register('POST', '/v1/a/new_container', HTTPOk, {})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
@ -653,7 +757,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_over_count_quota_obj_post_still_works(self):
|
def test_over_count_quota_obj_post_still_works(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-object-count': '101',
|
'x-account-object-count': '101',
|
||||||
'x-account-meta-quota-count': '100'})
|
'x-account-sysmeta-quota-count': '100'})
|
||||||
self.app.register('POST', '/v1/a/c/o', HTTPOk, {})
|
self.app.register('POST', '/v1/a/c/o', HTTPOk, {})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
@ -667,7 +771,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_exceed_count_quota_reseller(self):
|
def test_exceed_count_quota_reseller(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-object-count': '1000',
|
'x-account-object-count': '1000',
|
||||||
'x-account-meta-quota-count': '0'})
|
'x-account-sysmeta-quota-count': '0'})
|
||||||
self.app.register('PUT', '/v1/a', HTTPOk, {})
|
self.app.register('PUT', '/v1/a', HTTPOk, {})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
@ -681,7 +785,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_exceed_count_quota_reseller_copy_from(self):
|
def test_exceed_count_quota_reseller_copy_from(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-object-count': '10',
|
'x-account-object-count': '10',
|
||||||
'x-account-meta-quota-count': '10'})
|
'x-account-sysmeta-quota-count': '10'})
|
||||||
self.app.register('GET', '/v1/a/c2/o2', HTTPOk, {
|
self.app.register('GET', '/v1/a/c2/o2', HTTPOk, {
|
||||||
'content-length': '1000'}, b'a' * 1000)
|
'content-length': '1000'}, b'a' * 1000)
|
||||||
app = copy.filter_factory({})(
|
app = copy.filter_factory({})(
|
||||||
@ -698,7 +802,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_exceed_count_quota_reseller_copy_verb(self):
|
def test_exceed_count_quota_reseller_copy_verb(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-object-count': '99',
|
'x-account-object-count': '99',
|
||||||
'x-account-meta-quota-count': '100'})
|
'x-account-sysmeta-quota-count': '100'})
|
||||||
self.app.register('GET', '/v1/a/c2/o2', HTTPOk, {
|
self.app.register('GET', '/v1/a/c2/o2', HTTPOk, {
|
||||||
'content-length': '1000'}, b'a' * 1000)
|
'content-length': '1000'}, b'a' * 1000)
|
||||||
app = copy.filter_factory({})(
|
app = copy.filter_factory({})(
|
||||||
@ -715,7 +819,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
def test_not_exceed_count_quota(self):
|
def test_not_exceed_count_quota(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||||
'x-account-object-count': '10',
|
'x-account-object-count': '10',
|
||||||
'x-account-meta-quota-count': '20'})
|
'x-account-sysmeta-quota-count': '20'})
|
||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o',
|
req = Request.blank('/v1/a/c/o',
|
||||||
@ -730,7 +834,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
req = Request.blank('/v1/a',
|
req = Request.blank('/v1/a',
|
||||||
environ={'REQUEST_METHOD': 'POST',
|
environ={'REQUEST_METHOD': 'POST',
|
||||||
'swift.cache': cache,
|
'swift.cache': cache,
|
||||||
'HTTP_X_ACCOUNT_META_QUOTA_COUNT': 'abc',
|
'HTTP_X_ACCOUNT_QUOTA_COUNT': 'abc',
|
||||||
'reseller_request': True})
|
'reseller_request': True})
|
||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 400)
|
self.assertEqual(res.status_int, 400)
|
||||||
@ -742,7 +846,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
req = Request.blank('/v1/a',
|
req = Request.blank('/v1/a',
|
||||||
environ={'REQUEST_METHOD': 'POST',
|
environ={'REQUEST_METHOD': 'POST',
|
||||||
'swift.cache': cache,
|
'swift.cache': cache,
|
||||||
'HTTP_X_ACCOUNT_META_QUOTA_COUNT': '100'})
|
'HTTP_X_ACCOUNT_QUOTA_COUNT': '100'})
|
||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 403)
|
self.assertEqual(res.status_int, 403)
|
||||||
self.assertEqual(self.app.calls, [])
|
self.assertEqual(self.app.calls, [])
|
||||||
@ -765,13 +869,14 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
req = Request.blank('/v1/a',
|
req = Request.blank('/v1/a',
|
||||||
environ={'REQUEST_METHOD': 'POST',
|
environ={'REQUEST_METHOD': 'POST',
|
||||||
'swift.cache': cache,
|
'swift.cache': cache,
|
||||||
'HTTP_X_ACCOUNT_META_QUOTA_COUNT': '100',
|
'HTTP_X_ACCOUNT_QUOTA_COUNT': '100',
|
||||||
'reseller_request': True})
|
'reseller_request': True})
|
||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
self.assertEqual(self.app.calls_with_headers, [
|
self.assertEqual(self.app.calls_with_headers, [
|
||||||
('POST', '/v1/a', {'Host': 'localhost:80',
|
('POST', '/v1/a', {'Host': 'localhost:80',
|
||||||
'X-Account-Meta-Quota-Count': '100'})])
|
'X-Account-Quota-Count': '100',
|
||||||
|
'X-Account-Sysmeta-Quota-Count': '100'})])
|
||||||
|
|
||||||
@patch_policies
|
@patch_policies
|
||||||
def test_valid_policy_count_quota_reseller(self):
|
def test_valid_policy_count_quota_reseller(self):
|
||||||
@ -795,7 +900,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
req = Request.blank('/v1/a',
|
req = Request.blank('/v1/a',
|
||||||
environ={'REQUEST_METHOD': 'POST',
|
environ={'REQUEST_METHOD': 'POST',
|
||||||
'swift.cache': cache,
|
'swift.cache': cache,
|
||||||
'HTTP_X_ACCOUNT_META_QUOTA_COUNT': ''})
|
'HTTP_X_ACCOUNT_QUOTA_COUNT': ''})
|
||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 403)
|
self.assertEqual(res.status_int, 403)
|
||||||
|
|
||||||
@ -805,7 +910,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
req = Request.blank('/v1/a', environ={
|
req = Request.blank('/v1/a', environ={
|
||||||
'REQUEST_METHOD': 'POST',
|
'REQUEST_METHOD': 'POST',
|
||||||
'swift.cache': cache,
|
'swift.cache': cache,
|
||||||
'HTTP_X_REMOVE_ACCOUNT_META_QUOTA_COUNT': 'True'})
|
'HTTP_X_REMOVE_ACCOUNT_QUOTA_COUNT': 'True'})
|
||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 403)
|
self.assertEqual(res.status_int, 403)
|
||||||
|
|
||||||
@ -813,7 +918,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||||
req = Request.blank('/v1/a',
|
req = Request.blank('/v1/a',
|
||||||
environ={'REQUEST_METHOD': 'POST',
|
environ={'REQUEST_METHOD': 'POST',
|
||||||
'HTTP_X_ACCOUNT_META_QUOTA_COUNT': '',
|
'HTTP_X_ACCOUNT_QUOTA_COUNT': '',
|
||||||
'reseller_request': True})
|
'reseller_request': True})
|
||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
@ -824,7 +929,7 @@ class TestAccountQuota(unittest.TestCase):
|
|||||||
req = Request.blank('/v1/a', environ={
|
req = Request.blank('/v1/a', environ={
|
||||||
'REQUEST_METHOD': 'POST',
|
'REQUEST_METHOD': 'POST',
|
||||||
'swift.cache': cache,
|
'swift.cache': cache,
|
||||||
'HTTP_X_REMOVE_ACCOUNT_META_QUOTA_COUNT': 'True',
|
'HTTP_X_REMOVE_ACCOUNT_QUOTA_COUNT': 'True',
|
||||||
'reseller_request': True})
|
'reseller_request': True})
|
||||||
res = req.get_response(app)
|
res = req.get_response(app)
|
||||||
self.assertEqual(res.status_int, 200)
|
self.assertEqual(res.status_int, 200)
|
||||||
@ -844,7 +949,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
|||||||
def test_exceed_bytes_quota_copy_from(self):
|
def test_exceed_bytes_quota_copy_from(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||||
[('x-account-bytes-used', '500'),
|
[('x-account-bytes-used', '500'),
|
||||||
('x-account-meta-quota-bytes', '1000')])
|
('x-account-sysmeta-quota-bytes', '1000')])
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o',
|
req = Request.blank('/v1/a/c/o',
|
||||||
environ={'REQUEST_METHOD': 'PUT',
|
environ={'REQUEST_METHOD': 'PUT',
|
||||||
@ -857,7 +962,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
|||||||
def test_exceed_bytes_quota_copy_verb(self):
|
def test_exceed_bytes_quota_copy_verb(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||||
[('x-account-bytes-used', '500'),
|
[('x-account-bytes-used', '500'),
|
||||||
('x-account-meta-quota-bytes', '1000')])
|
('x-account-sysmeta-quota-bytes', '1000')])
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c2/o2',
|
req = Request.blank('/v1/a/c2/o2',
|
||||||
environ={'REQUEST_METHOD': 'COPY',
|
environ={'REQUEST_METHOD': 'COPY',
|
||||||
@ -871,7 +976,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
|||||||
self.app.register('PUT', '/v1/a/c/o', HTTPOk, {})
|
self.app.register('PUT', '/v1/a/c/o', HTTPOk, {})
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||||
[('x-account-bytes-used', '0'),
|
[('x-account-bytes-used', '0'),
|
||||||
('x-account-meta-quota-bytes', '1000')])
|
('x-account-sysmeta-quota-bytes', '1000')])
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o',
|
req = Request.blank('/v1/a/c/o',
|
||||||
environ={'REQUEST_METHOD': 'PUT',
|
environ={'REQUEST_METHOD': 'PUT',
|
||||||
@ -884,7 +989,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
|||||||
self.app.register('PUT', '/v1/a/c/o', HTTPOk, {})
|
self.app.register('PUT', '/v1/a/c/o', HTTPOk, {})
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||||
[('x-account-bytes-used', '0'),
|
[('x-account-bytes-used', '0'),
|
||||||
('x-account-meta-quota-bytes', '1000')])
|
('x-account-sysmeta-quota-bytes', '1000')])
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c2/o2',
|
req = Request.blank('/v1/a/c2/o2',
|
||||||
environ={'REQUEST_METHOD': 'COPY',
|
environ={'REQUEST_METHOD': 'COPY',
|
||||||
@ -896,7 +1001,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
|||||||
def test_quota_copy_from_bad_src(self):
|
def test_quota_copy_from_bad_src(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||||
[('x-account-bytes-used', '0'),
|
[('x-account-bytes-used', '0'),
|
||||||
('x-account-meta-quota-bytes', '1000')])
|
('x-account-sysmeta-quota-bytes', '1000')])
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o',
|
req = Request.blank('/v1/a/c/o',
|
||||||
environ={'REQUEST_METHOD': 'PUT',
|
environ={'REQUEST_METHOD': 'PUT',
|
||||||
@ -907,14 +1012,14 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
|||||||
|
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||||
[('x-account-bytes-used', '1000'),
|
[('x-account-bytes-used', '1000'),
|
||||||
('x-account-meta-quota-bytes', '0')])
|
('x-account-sysmeta-quota-bytes', '0')])
|
||||||
res = req.get_response(self.copy_filter)
|
res = req.get_response(self.copy_filter)
|
||||||
self.assertEqual(res.status_int, 412)
|
self.assertEqual(res.status_int, 412)
|
||||||
|
|
||||||
def test_exceed_bytes_count_quota_copy_from(self):
|
def test_exceed_bytes_count_quota_copy_from(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||||
[('x-account-object-count', '5'),
|
[('x-account-object-count', '5'),
|
||||||
('x-account-meta-quota-count', '5')])
|
('x-account-sysmeta-quota-count', '5')])
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o',
|
req = Request.blank('/v1/a/c/o',
|
||||||
environ={'REQUEST_METHOD': 'PUT',
|
environ={'REQUEST_METHOD': 'PUT',
|
||||||
@ -927,7 +1032,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
|||||||
def test_exceed_bytes_count_quota_copy_verb(self):
|
def test_exceed_bytes_count_quota_copy_verb(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||||
[('x-account-object-count', '5'),
|
[('x-account-object-count', '5'),
|
||||||
('x-account-meta-quota-count', '5')])
|
('x-account-sysmeta-quota-count', '5')])
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c2/o2',
|
req = Request.blank('/v1/a/c2/o2',
|
||||||
environ={'REQUEST_METHOD': 'COPY',
|
environ={'REQUEST_METHOD': 'COPY',
|
||||||
@ -941,7 +1046,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
|||||||
self.app.register('PUT', '/v1/a/c/o', HTTPOk, {})
|
self.app.register('PUT', '/v1/a/c/o', HTTPOk, {})
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||||
[('x-account-object-count', '5'),
|
[('x-account-object-count', '5'),
|
||||||
('x-account-meta-quota-count', '6')])
|
('x-account-sysmeta-quota-count', '6')])
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o',
|
req = Request.blank('/v1/a/c/o',
|
||||||
environ={'REQUEST_METHOD': 'PUT',
|
environ={'REQUEST_METHOD': 'PUT',
|
||||||
@ -954,7 +1059,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
|||||||
self.app.register('PUT', '/v1/a/c/o', HTTPOk, {})
|
self.app.register('PUT', '/v1/a/c/o', HTTPOk, {})
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||||
[('x-account-object-count', '5'),
|
[('x-account-object-count', '5'),
|
||||||
('x-account-meta-quota-count', '6')])
|
('x-account-sysmeta-quota-count', '6')])
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c2/o2',
|
req = Request.blank('/v1/a/c2/o2',
|
||||||
environ={'REQUEST_METHOD': 'COPY',
|
environ={'REQUEST_METHOD': 'COPY',
|
||||||
@ -966,7 +1071,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
|||||||
def test_count_quota_copy_from_bad_src(self):
|
def test_count_quota_copy_from_bad_src(self):
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||||
[('x-account-object-count', '0'),
|
[('x-account-object-count', '0'),
|
||||||
('x-account-meta-quota-count', '1')])
|
('x-account-sysmeta-quota-count', '1')])
|
||||||
cache = FakeCache(None)
|
cache = FakeCache(None)
|
||||||
req = Request.blank('/v1/a/c/o',
|
req = Request.blank('/v1/a/c/o',
|
||||||
environ={'REQUEST_METHOD': 'PUT',
|
environ={'REQUEST_METHOD': 'PUT',
|
||||||
@ -977,7 +1082,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
|||||||
|
|
||||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||||
[('x-account-object-count', '1'),
|
[('x-account-object-count', '1'),
|
||||||
('x-account-meta-quota-count', '0')])
|
('x-account-sysmeta-quota-count', '0')])
|
||||||
res = req.get_response(self.copy_filter)
|
res = req.get_response(self.copy_filter)
|
||||||
self.assertEqual(res.status_int, 412)
|
self.assertEqual(res.status_int, 412)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user