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 |
|
||||
+=============================================+===============================+
|
||||
| X-Account-Meta-Quota-Bytes | Maximum overall bytes stored |
|
||||
| X-Account-Meta-Quota-Bytes (obsoleted) | Maximum overall bytes stored |
|
||||
| | 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. |
|
||||
+---------------------------------------------+-------------------------------+
|
||||
| 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.
|
||||
@ -95,9 +105,9 @@ class AccountQuotaMiddleware(object):
|
||||
def validate_and_translate_quotas(self, request, quota_type):
|
||||
new_quotas = {}
|
||||
new_quotas[None] = request.headers.get(
|
||||
'X-Account-Meta-%s' % quota_type)
|
||||
'X-Account-%s' % quota_type)
|
||||
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
|
||||
|
||||
for policy in POLICIES:
|
||||
@ -114,8 +124,9 @@ class AccountQuotaMiddleware(object):
|
||||
raise HTTPBadRequest()
|
||||
for idx, quota in new_quotas.items():
|
||||
if idx is None:
|
||||
continue # For legacy reasons, it's in user meta
|
||||
hdr = 'X-Account-Sysmeta-%s-Policy-%d' % (quota_type, idx)
|
||||
hdr = 'X-Account-Sysmeta-%s' % quota_type
|
||||
else:
|
||||
hdr = 'X-Account-Sysmeta-%s-Policy-%d' % (quota_type, idx)
|
||||
request.headers[hdr] = quota
|
||||
elif any(quota is not None for quota in new_quotas.values()):
|
||||
# deny quota set for non-reseller
|
||||
@ -123,11 +134,29 @@ class AccountQuotaMiddleware(object):
|
||||
|
||||
def handle_account(self, request):
|
||||
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
|
||||
self.validate_and_translate_quotas(request, "Quota-Bytes")
|
||||
self.validate_and_translate_quotas(request, "Quota-Count")
|
||||
resp = request.get_response(self.app)
|
||||
# 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:
|
||||
infixes = ('Quota-Bytes-Policy', 'Quota-Count-Policy')
|
||||
for infix in infixes:
|
||||
@ -170,7 +199,11 @@ class AccountQuotaMiddleware(object):
|
||||
|
||||
# Check for quota byte violation
|
||||
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:
|
||||
quota = -1
|
||||
if quota >= 0:
|
||||
@ -191,7 +224,7 @@ class AccountQuotaMiddleware(object):
|
||||
|
||||
# Check for quota count violation
|
||||
try:
|
||||
quota = int(account_info['meta'].get('quota-count', -1))
|
||||
quota = int(account_info['sysmeta'].get('quota-count', -1))
|
||||
except ValueError:
|
||||
quota = -1
|
||||
if quota >= 0:
|
||||
|
@ -968,10 +968,9 @@ class TestAccountQuotas(unittest.TestCase):
|
||||
resp.read()
|
||||
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:
|
||||
raise SkipTest('No admin user configured')
|
||||
quota_header = 'X-Account-Meta-Quota-Bytes'
|
||||
|
||||
def get_current_quota():
|
||||
def head(url, token, parsed, conn):
|
||||
@ -984,7 +983,9 @@ class TestAccountQuotas(unittest.TestCase):
|
||||
resp = retry(head)
|
||||
resp.read()
|
||||
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()
|
||||
|
||||
@ -1008,6 +1009,14 @@ class TestAccountQuotas(unittest.TestCase):
|
||||
finally:
|
||||
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):
|
||||
if tf.skip_if_no_reseller_admin:
|
||||
raise SkipTest('No admin user configured')
|
||||
|
@ -109,7 +109,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
# activation of the account-quota middleware
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'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)
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o',
|
||||
@ -118,7 +118,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
res = req.get_response(app)
|
||||
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, {
|
||||
'x-account-bytes-used': '1000',
|
||||
'x-account-meta-quota-bytes': '0'})
|
||||
@ -131,13 +131,26 @@ class TestAccountQuota(unittest.TestCase):
|
||||
self.assertEqual(res.status_int, 413)
|
||||
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
|
||||
def test_exceed_per_policy_quota(self):
|
||||
self.app.register('HEAD', '/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-meta-quota-bytes': '1000'})
|
||||
'x-account-sysmeta-quota-bytes': '1000'})
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o',
|
||||
@ -148,13 +161,15 @@ class TestAccountQuota(unittest.TestCase):
|
||||
self.assertEqual(res.body, b'Upload exceeds policy quota.')
|
||||
|
||||
@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):
|
||||
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-meta-quota-bytes': '1000'})
|
||||
'x-account-sysmeta-quota-bytes': '1000',
|
||||
'x-account-meta-quota-bytes': '2000'})
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a', method=method, environ={
|
||||
@ -162,7 +177,37 @@ class TestAccountQuota(unittest.TestCase):
|
||||
res = req.get_response(app)
|
||||
self.assertEqual(res.status_int, 200)
|
||||
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(
|
||||
'X-Account-Sysmeta-Quota-Bytes-Policy-1'), '10')
|
||||
self.assertEqual(res.headers.get(
|
||||
@ -176,7 +221,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_exceed_quota_not_authorized(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'x-account-bytes-used': '1000',
|
||||
'x-account-meta-quota-bytes': '0'})
|
||||
'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',
|
||||
@ -185,7 +230,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
res = req.get_response(app)
|
||||
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, {
|
||||
'x-account-bytes-used': '1000',
|
||||
'x-account-meta-quota-bytes': '0'})
|
||||
@ -197,10 +242,22 @@ class TestAccountQuota(unittest.TestCase):
|
||||
res = req.get_response(app)
|
||||
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):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'x-account-bytes-used': '0',
|
||||
'x-account-meta-quota-bytes': '1000'})
|
||||
'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',
|
||||
@ -209,7 +266,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
res = req.get_response(app)
|
||||
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, {
|
||||
'x-account-bytes-used': '0',
|
||||
'x-account-meta-quota-bytes': '1000'})
|
||||
@ -221,10 +278,22 @@ class TestAccountQuota(unittest.TestCase):
|
||||
res = req.get_response(app)
|
||||
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, {
|
||||
'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))
|
||||
cache = FakeCache(None)
|
||||
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.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, {
|
||||
'x-account-bytes-used': '100',
|
||||
'x-account-meta-quota-bytes': '1000'})
|
||||
'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',
|
||||
@ -252,7 +321,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_over_quota_container_create_still_works(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'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, {})
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
@ -266,7 +335,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_over_quota_container_post_still_works(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'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, {})
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
@ -280,7 +349,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_over_quota_obj_post_still_works(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'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, {})
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
@ -294,7 +363,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_exceed_bytes_quota_reseller(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'x-account-bytes-used': '1000',
|
||||
'x-account-meta-quota-bytes': '0'})
|
||||
'x-account-sysmeta-quota-bytes': '0'})
|
||||
self.app.register('PUT', '/v1/a', HTTPOk, {})
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
@ -308,7 +377,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_exceed_bytes_quota_reseller_copy_from(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'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, {
|
||||
'content-length': '1000'}, b'a' * 1000)
|
||||
app = copy.filter_factory({})(
|
||||
@ -325,7 +394,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_exceed_bytes_quota_reseller_copy_verb(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'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, {
|
||||
'content-length': '1000'}, b'a' * 1000)
|
||||
app = copy.filter_factory({})(
|
||||
@ -361,7 +430,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_not_exceed_bytes_quota(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'x-account-bytes-used': '1000',
|
||||
'x-account-meta-quota-bytes': '2000'})
|
||||
'x-account-sysmeta-quota-bytes': '2000'})
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o',
|
||||
@ -376,7 +445,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
req = Request.blank('/v1/a',
|
||||
environ={'REQUEST_METHOD': 'POST',
|
||||
'swift.cache': cache,
|
||||
'HTTP_X_ACCOUNT_META_QUOTA_BYTES': 'abc',
|
||||
'HTTP_X_ACCOUNT_QUOTA_BYTES': 'abc',
|
||||
'reseller_request': True})
|
||||
res = req.get_response(app)
|
||||
self.assertEqual(res.status_int, 400)
|
||||
@ -395,13 +464,13 @@ class TestAccountQuota(unittest.TestCase):
|
||||
self.assertEqual(res.status_int, 400)
|
||||
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)
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a',
|
||||
environ={'REQUEST_METHOD': 'POST',
|
||||
'swift.cache': cache,
|
||||
'HTTP_X_ACCOUNT_META_QUOTA_BYTES': '100'})
|
||||
'HTTP_X_ACCOUNT_QUOTA_BYTES': '100'})
|
||||
res = req.get_response(app)
|
||||
self.assertEqual(res.status_int, 403)
|
||||
self.assertEqual(self.app.calls, [])
|
||||
@ -418,7 +487,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
self.assertEqual(res.status_int, 403)
|
||||
self.assertEqual(self.app.calls, [])
|
||||
|
||||
def test_valid_quotas_reseller(self):
|
||||
def test_valid_quotas_reseller_legacy(self):
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a',
|
||||
@ -430,7 +499,42 @@ class TestAccountQuota(unittest.TestCase):
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertEqual(self.app.calls_with_headers, [
|
||||
('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
|
||||
def test_valid_policy_quota_reseller(self):
|
||||
@ -454,7 +558,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
req = Request.blank('/v1/a',
|
||||
environ={'REQUEST_METHOD': 'POST',
|
||||
'swift.cache': cache,
|
||||
'HTTP_X_ACCOUNT_META_QUOTA_BYTES': ''})
|
||||
'HTTP_X_ACCOUNT_QUOTA_BYTES': ''})
|
||||
res = req.get_response(app)
|
||||
self.assertEqual(res.status_int, 403)
|
||||
|
||||
@ -464,7 +568,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
req = Request.blank('/v1/a', environ={
|
||||
'REQUEST_METHOD': 'POST',
|
||||
'swift.cache': cache,
|
||||
'HTTP_X_REMOVE_ACCOUNT_META_QUOTA_BYTES': 'True'})
|
||||
'HTTP_X_REMOVE_ACCOUNT_QUOTA_BYTES': 'True'})
|
||||
res = req.get_response(app)
|
||||
self.assertEqual(res.status_int, 403)
|
||||
|
||||
@ -472,7 +576,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
req = Request.blank('/v1/a',
|
||||
environ={'REQUEST_METHOD': 'POST',
|
||||
'HTTP_X_ACCOUNT_META_QUOTA_BYTES': '',
|
||||
'HTTP_X_ACCOUNT_QUOTA_BYTES': '',
|
||||
'reseller_request': True})
|
||||
res = req.get_response(app)
|
||||
self.assertEqual(res.status_int, 200)
|
||||
@ -483,7 +587,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
req = Request.blank('/v1/a', environ={
|
||||
'REQUEST_METHOD': 'POST',
|
||||
'swift.cache': cache,
|
||||
'HTTP_X_REMOVE_ACCOUNT_META_QUOTA_BYTES': 'True',
|
||||
'HTTP_X_REMOVE_ACCOUNT_QUOTA_BYTES': 'True',
|
||||
'reseller_request': True})
|
||||
res = req.get_response(app)
|
||||
self.assertEqual(res.status_int, 200)
|
||||
@ -541,7 +645,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_exceed_count_quota(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'x-account-object-count': '10',
|
||||
'x-account-meta-quota-count': '10'})
|
||||
'x-account-sysmeta-quota-count': '10'})
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o',
|
||||
@ -553,7 +657,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
|
||||
def test_exceed_quota_count_not_authorized(self):
|
||||
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))
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||
@ -564,7 +668,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
|
||||
def test_exceed_count_quota_authorized(self):
|
||||
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))
|
||||
cache = FakeCache(None)
|
||||
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):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'x-account-object-count': '0',
|
||||
'x-account-meta-quota-count': '5'})
|
||||
'x-account-sysmeta-quota-count': '5'})
|
||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||
@ -588,7 +692,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_under_quota_count_authorized(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'x-account-object-count': '0',
|
||||
'x-account-meta-quota-count': '5'})
|
||||
'x-account-sysmeta-quota-count': '5'})
|
||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||
cache = FakeCache(None)
|
||||
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):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'x-account-object-count': '0',
|
||||
'x-account-meta-quota-count': '0'})
|
||||
'x-account-sysmeta-quota-count': '0'})
|
||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o', method='PUT',
|
||||
@ -612,7 +716,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_exceed_quota_count_authorized(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'x-account-object-count': '5',
|
||||
'x-account-meta-quota-count': '5'})
|
||||
'x-account-sysmeta-quota-count': '5'})
|
||||
app = FakeAuthFilter(account_quotas.AccountQuotaMiddleware(self.app))
|
||||
cache = FakeCache(None)
|
||||
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):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'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, {})
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
@ -639,7 +743,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_over_quota_count_container_post_still_works(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'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, {})
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
@ -653,7 +757,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_over_count_quota_obj_post_still_works(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'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, {})
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
@ -667,7 +771,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_exceed_count_quota_reseller(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'x-account-object-count': '1000',
|
||||
'x-account-meta-quota-count': '0'})
|
||||
'x-account-sysmeta-quota-count': '0'})
|
||||
self.app.register('PUT', '/v1/a', HTTPOk, {})
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
@ -681,7 +785,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_exceed_count_quota_reseller_copy_from(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'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, {
|
||||
'content-length': '1000'}, b'a' * 1000)
|
||||
app = copy.filter_factory({})(
|
||||
@ -698,7 +802,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_exceed_count_quota_reseller_copy_verb(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'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, {
|
||||
'content-length': '1000'}, b'a' * 1000)
|
||||
app = copy.filter_factory({})(
|
||||
@ -715,7 +819,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
def test_not_exceed_count_quota(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk, {
|
||||
'x-account-object-count': '10',
|
||||
'x-account-meta-quota-count': '20'})
|
||||
'x-account-sysmeta-quota-count': '20'})
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o',
|
||||
@ -730,7 +834,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
req = Request.blank('/v1/a',
|
||||
environ={'REQUEST_METHOD': 'POST',
|
||||
'swift.cache': cache,
|
||||
'HTTP_X_ACCOUNT_META_QUOTA_COUNT': 'abc',
|
||||
'HTTP_X_ACCOUNT_QUOTA_COUNT': 'abc',
|
||||
'reseller_request': True})
|
||||
res = req.get_response(app)
|
||||
self.assertEqual(res.status_int, 400)
|
||||
@ -742,7 +846,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
req = Request.blank('/v1/a',
|
||||
environ={'REQUEST_METHOD': 'POST',
|
||||
'swift.cache': cache,
|
||||
'HTTP_X_ACCOUNT_META_QUOTA_COUNT': '100'})
|
||||
'HTTP_X_ACCOUNT_QUOTA_COUNT': '100'})
|
||||
res = req.get_response(app)
|
||||
self.assertEqual(res.status_int, 403)
|
||||
self.assertEqual(self.app.calls, [])
|
||||
@ -765,13 +869,14 @@ class TestAccountQuota(unittest.TestCase):
|
||||
req = Request.blank('/v1/a',
|
||||
environ={'REQUEST_METHOD': 'POST',
|
||||
'swift.cache': cache,
|
||||
'HTTP_X_ACCOUNT_META_QUOTA_COUNT': '100',
|
||||
'HTTP_X_ACCOUNT_QUOTA_COUNT': '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-Meta-Quota-Count': '100'})])
|
||||
'X-Account-Quota-Count': '100',
|
||||
'X-Account-Sysmeta-Quota-Count': '100'})])
|
||||
|
||||
@patch_policies
|
||||
def test_valid_policy_count_quota_reseller(self):
|
||||
@ -795,7 +900,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
req = Request.blank('/v1/a',
|
||||
environ={'REQUEST_METHOD': 'POST',
|
||||
'swift.cache': cache,
|
||||
'HTTP_X_ACCOUNT_META_QUOTA_COUNT': ''})
|
||||
'HTTP_X_ACCOUNT_QUOTA_COUNT': ''})
|
||||
res = req.get_response(app)
|
||||
self.assertEqual(res.status_int, 403)
|
||||
|
||||
@ -805,7 +910,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
req = Request.blank('/v1/a', environ={
|
||||
'REQUEST_METHOD': 'POST',
|
||||
'swift.cache': cache,
|
||||
'HTTP_X_REMOVE_ACCOUNT_META_QUOTA_COUNT': 'True'})
|
||||
'HTTP_X_REMOVE_ACCOUNT_QUOTA_COUNT': 'True'})
|
||||
res = req.get_response(app)
|
||||
self.assertEqual(res.status_int, 403)
|
||||
|
||||
@ -813,7 +918,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
app = account_quotas.AccountQuotaMiddleware(self.app)
|
||||
req = Request.blank('/v1/a',
|
||||
environ={'REQUEST_METHOD': 'POST',
|
||||
'HTTP_X_ACCOUNT_META_QUOTA_COUNT': '',
|
||||
'HTTP_X_ACCOUNT_QUOTA_COUNT': '',
|
||||
'reseller_request': True})
|
||||
res = req.get_response(app)
|
||||
self.assertEqual(res.status_int, 200)
|
||||
@ -824,7 +929,7 @@ class TestAccountQuota(unittest.TestCase):
|
||||
req = Request.blank('/v1/a', environ={
|
||||
'REQUEST_METHOD': 'POST',
|
||||
'swift.cache': cache,
|
||||
'HTTP_X_REMOVE_ACCOUNT_META_QUOTA_COUNT': 'True',
|
||||
'HTTP_X_REMOVE_ACCOUNT_QUOTA_COUNT': 'True',
|
||||
'reseller_request': True})
|
||||
res = req.get_response(app)
|
||||
self.assertEqual(res.status_int, 200)
|
||||
@ -844,7 +949,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
||||
def test_exceed_bytes_quota_copy_from(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||
[('x-account-bytes-used', '500'),
|
||||
('x-account-meta-quota-bytes', '1000')])
|
||||
('x-account-sysmeta-quota-bytes', '1000')])
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o',
|
||||
environ={'REQUEST_METHOD': 'PUT',
|
||||
@ -857,7 +962,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
||||
def test_exceed_bytes_quota_copy_verb(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||
[('x-account-bytes-used', '500'),
|
||||
('x-account-meta-quota-bytes', '1000')])
|
||||
('x-account-sysmeta-quota-bytes', '1000')])
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c2/o2',
|
||||
environ={'REQUEST_METHOD': 'COPY',
|
||||
@ -871,7 +976,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
||||
self.app.register('PUT', '/v1/a/c/o', HTTPOk, {})
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||
[('x-account-bytes-used', '0'),
|
||||
('x-account-meta-quota-bytes', '1000')])
|
||||
('x-account-sysmeta-quota-bytes', '1000')])
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o',
|
||||
environ={'REQUEST_METHOD': 'PUT',
|
||||
@ -884,7 +989,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
||||
self.app.register('PUT', '/v1/a/c/o', HTTPOk, {})
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||
[('x-account-bytes-used', '0'),
|
||||
('x-account-meta-quota-bytes', '1000')])
|
||||
('x-account-sysmeta-quota-bytes', '1000')])
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c2/o2',
|
||||
environ={'REQUEST_METHOD': 'COPY',
|
||||
@ -896,7 +1001,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
||||
def test_quota_copy_from_bad_src(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||
[('x-account-bytes-used', '0'),
|
||||
('x-account-meta-quota-bytes', '1000')])
|
||||
('x-account-sysmeta-quota-bytes', '1000')])
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o',
|
||||
environ={'REQUEST_METHOD': 'PUT',
|
||||
@ -907,14 +1012,14 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
||||
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||
[('x-account-bytes-used', '1000'),
|
||||
('x-account-meta-quota-bytes', '0')])
|
||||
('x-account-sysmeta-quota-bytes', '0')])
|
||||
res = req.get_response(self.copy_filter)
|
||||
self.assertEqual(res.status_int, 412)
|
||||
|
||||
def test_exceed_bytes_count_quota_copy_from(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||
[('x-account-object-count', '5'),
|
||||
('x-account-meta-quota-count', '5')])
|
||||
('x-account-sysmeta-quota-count', '5')])
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o',
|
||||
environ={'REQUEST_METHOD': 'PUT',
|
||||
@ -927,7 +1032,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
||||
def test_exceed_bytes_count_quota_copy_verb(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||
[('x-account-object-count', '5'),
|
||||
('x-account-meta-quota-count', '5')])
|
||||
('x-account-sysmeta-quota-count', '5')])
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c2/o2',
|
||||
environ={'REQUEST_METHOD': 'COPY',
|
||||
@ -941,7 +1046,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
||||
self.app.register('PUT', '/v1/a/c/o', HTTPOk, {})
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||
[('x-account-object-count', '5'),
|
||||
('x-account-meta-quota-count', '6')])
|
||||
('x-account-sysmeta-quota-count', '6')])
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o',
|
||||
environ={'REQUEST_METHOD': 'PUT',
|
||||
@ -954,7 +1059,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
||||
self.app.register('PUT', '/v1/a/c/o', HTTPOk, {})
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||
[('x-account-object-count', '5'),
|
||||
('x-account-meta-quota-count', '6')])
|
||||
('x-account-sysmeta-quota-count', '6')])
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c2/o2',
|
||||
environ={'REQUEST_METHOD': 'COPY',
|
||||
@ -966,7 +1071,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
||||
def test_count_quota_copy_from_bad_src(self):
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||
[('x-account-object-count', '0'),
|
||||
('x-account-meta-quota-count', '1')])
|
||||
('x-account-sysmeta-quota-count', '1')])
|
||||
cache = FakeCache(None)
|
||||
req = Request.blank('/v1/a/c/o',
|
||||
environ={'REQUEST_METHOD': 'PUT',
|
||||
@ -977,7 +1082,7 @@ class AccountQuotaCopyingTestCases(unittest.TestCase):
|
||||
|
||||
self.app.register('HEAD', '/v1/a', HTTPOk,
|
||||
[('x-account-object-count', '1'),
|
||||
('x-account-meta-quota-count', '0')])
|
||||
('x-account-sysmeta-quota-count', '0')])
|
||||
res = req.get_response(self.copy_filter)
|
||||
self.assertEqual(res.status_int, 412)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user