User quota update should not exceed project quota
Move the default user quota setting code from db to quota.py, because it is necessary to check if user quota is set in db to get the settable quota for the user under a project. Fixes bug 1208400 Change-Id: I83a4a7fcd8bf80b20e4e700bad7dd31294f8ed0b
This commit is contained in:
parent
8fb450fb3a
commit
b4905b40fd
@ -2640,16 +2640,7 @@ def quota_get_all_by_project_and_user(context, project_id, user_id):
|
||||
filter_by(user_id=user_id).\
|
||||
all()
|
||||
|
||||
proj_quotas = model_query(context, models.Quota.resource,
|
||||
models.Quota.hard_limit,
|
||||
base_model=models.Quota).\
|
||||
filter_by(project_id=project_id).\
|
||||
all()
|
||||
|
||||
result = {'project_id': project_id, 'user_id': user_id}
|
||||
# Use the project quota for default user quota.
|
||||
for quota in proj_quotas:
|
||||
result[quota.resource] = quota.hard_limit
|
||||
for quota in user_quotas:
|
||||
result[quota.resource] = quota.hard_limit
|
||||
|
||||
|
@ -222,6 +222,11 @@ class DbQuotaDriver(object):
|
||||
"""
|
||||
user_quotas = db.quota_get_all_by_project_and_user(context,
|
||||
project_id, user_id)
|
||||
# Use the project quota for default user quota.
|
||||
proj_quotas = db.quota_get_all_by_project(context, project_id)
|
||||
for key, value in proj_quotas.iteritems():
|
||||
if key not in user_quotas.keys():
|
||||
user_quotas[key] = value
|
||||
user_usages = None
|
||||
if usages:
|
||||
user_usages = db.quota_usage_get_all_by_project_and_user(context,
|
||||
|
@ -4764,18 +4764,6 @@ class QuotaTestCase(test.TestCase, ModelsObjectComparatorMixin):
|
||||
'resource2': 2})
|
||||
|
||||
def test_quota_get_all_by_project_and_user(self):
|
||||
for i in range(3):
|
||||
for j in range(3):
|
||||
db.quota_create(self.ctxt, 'proj%d' % i, 'resource%d' % j, j)
|
||||
for i in range(3):
|
||||
quotas_db = db.quota_get_all_by_project_and_user(self.ctxt,
|
||||
'proj%d' % i,
|
||||
'user%d' % i)
|
||||
self.assertEqual(quotas_db, {'project_id': 'proj%d' % i,
|
||||
'user_id': 'user%d' % i,
|
||||
'resource0': 0,
|
||||
'resource1': 1,
|
||||
'resource2': 2})
|
||||
for i in range(3):
|
||||
for j in range(3):
|
||||
db.quota_create(self.ctxt, 'proj%d' % i, 'resource%d' % j,
|
||||
@ -4876,10 +4864,7 @@ class QuotaTestCase(test.TestCase, ModelsObjectComparatorMixin):
|
||||
self.assertEqual(db.quota_get_all_by_project_and_user(self.ctxt,
|
||||
'project1', 'user1'),
|
||||
{'project_id': 'project1',
|
||||
'user_id': 'user1',
|
||||
'resource0': 0,
|
||||
'resource1': 1,
|
||||
'resource2': 2})
|
||||
'user_id': 'user1'})
|
||||
self.assertEqual(db.quota_usage_get_all_by_project_and_user(
|
||||
self.ctxt, 'project1', 'user1'),
|
||||
{'project_id': 'project1',
|
||||
|
@ -864,7 +864,7 @@ class DbQuotaDriverTestCase(test.TestCase):
|
||||
))
|
||||
|
||||
def _stub_get_by_project_and_user(self):
|
||||
def fake_qgabp(context, project_id, user_id):
|
||||
def fake_qgabpau(context, project_id, user_id):
|
||||
self.calls.append('quota_get_all_by_project_and_user')
|
||||
self.assertEqual(project_id, 'test_project')
|
||||
self.assertEqual(user_id, 'fake_user')
|
||||
@ -874,7 +874,16 @@ class DbQuotaDriverTestCase(test.TestCase):
|
||||
injected_file_path_bytes=127,
|
||||
)
|
||||
|
||||
def fake_qugabp(context, project_id, user_id):
|
||||
def fake_qgabp(context, project_id):
|
||||
self.calls.append('quota_get_all_by_project')
|
||||
self.assertEqual(project_id, 'test_project')
|
||||
return {
|
||||
'cores': 10,
|
||||
'injected_files': 2,
|
||||
'injected_file_path_bytes': 127,
|
||||
}
|
||||
|
||||
def fake_qugabpau(context, project_id, user_id):
|
||||
self.calls.append('quota_usage_get_all_by_project_and_user')
|
||||
self.assertEqual(project_id, 'test_project')
|
||||
self.assertEqual(user_id, 'fake_user')
|
||||
@ -889,9 +898,10 @@ class DbQuotaDriverTestCase(test.TestCase):
|
||||
injected_file_path_bytes=dict(in_use=0, reserved=0),
|
||||
)
|
||||
|
||||
self.stubs.Set(db, 'quota_get_all_by_project_and_user', fake_qgabp)
|
||||
self.stubs.Set(db, 'quota_get_all_by_project_and_user', fake_qgabpau)
|
||||
self.stubs.Set(db, 'quota_get_all_by_project', fake_qgabp)
|
||||
self.stubs.Set(db, 'quota_usage_get_all_by_project_and_user',
|
||||
fake_qugabp)
|
||||
fake_qugabpau)
|
||||
|
||||
self._stub_quota_class_get_all_by_name()
|
||||
|
||||
@ -904,6 +914,7 @@ class DbQuotaDriverTestCase(test.TestCase):
|
||||
|
||||
self.assertEqual(self.calls, [
|
||||
'quota_get_all_by_project_and_user',
|
||||
'quota_get_all_by_project',
|
||||
'quota_usage_get_all_by_project_and_user',
|
||||
'quota_class_get_all_by_name',
|
||||
])
|
||||
@ -1080,11 +1091,12 @@ class DbQuotaDriverTestCase(test.TestCase):
|
||||
self.maxDiff = None
|
||||
self._stub_get_by_project_and_user()
|
||||
result = self.driver.get_user_quotas(
|
||||
FakeContext('other_project', 'other_class'),
|
||||
FakeContext('test_project', None),
|
||||
quota.QUOTAS._resources, 'test_project', 'fake_user')
|
||||
|
||||
self.assertEqual(self.calls, [
|
||||
'quota_get_all_by_project_and_user',
|
||||
'quota_get_all_by_project',
|
||||
'quota_usage_get_all_by_project_and_user',
|
||||
])
|
||||
self.assertEqual(result, dict(
|
||||
@ -1103,7 +1115,7 @@ class DbQuotaDriverTestCase(test.TestCase):
|
||||
in_use=10 * 1024,
|
||||
reserved=0,
|
||||
),
|
||||
floating_ips=dict(
|
||||
floating_ips=dict(
|
||||
limit=10,
|
||||
in_use=2,
|
||||
reserved=0,
|
||||
@ -1229,12 +1241,13 @@ class DbQuotaDriverTestCase(test.TestCase):
|
||||
self.maxDiff = None
|
||||
self._stub_get_by_project_and_user()
|
||||
result = self.driver.get_user_quotas(
|
||||
FakeContext('other_project', 'other_class'),
|
||||
FakeContext('test_project', 'test_class'),
|
||||
quota.QUOTAS._resources, 'test_project', 'fake_user',
|
||||
quota_class='test_class')
|
||||
|
||||
self.assertEqual(self.calls, [
|
||||
'quota_get_all_by_project_and_user',
|
||||
'quota_get_all_by_project',
|
||||
'quota_usage_get_all_by_project_and_user',
|
||||
'quota_class_get_all_by_name',
|
||||
])
|
||||
@ -1386,6 +1399,7 @@ class DbQuotaDriverTestCase(test.TestCase):
|
||||
|
||||
self.assertEqual(self.calls, [
|
||||
'quota_get_all_by_project_and_user',
|
||||
'quota_get_all_by_project',
|
||||
'quota_usage_get_all_by_project_and_user',
|
||||
'quota_class_get_all_by_name',
|
||||
])
|
||||
@ -1445,6 +1459,7 @@ class DbQuotaDriverTestCase(test.TestCase):
|
||||
|
||||
self.assertEqual(self.calls, [
|
||||
'quota_get_all_by_project_and_user',
|
||||
'quota_get_all_by_project',
|
||||
'quota_class_get_all_by_name',
|
||||
])
|
||||
self.assertEqual(result, dict(
|
||||
@ -1536,6 +1551,170 @@ class DbQuotaDriverTestCase(test.TestCase):
|
||||
),
|
||||
))
|
||||
|
||||
def _stub_get_settable_quotas(self):
|
||||
def fake_get_project_quotas(context, resources, project_id,
|
||||
quota_class=None, defaults=True,
|
||||
usages=True, remains=False):
|
||||
self.calls.append('get_project_quotas')
|
||||
result = {}
|
||||
for k, v in resources.items():
|
||||
if k == 'instances':
|
||||
remains = v.default - 5
|
||||
in_use = 1
|
||||
else:
|
||||
remains = v.default
|
||||
in_use = 0
|
||||
result[k] = {'limit': v.default, 'in_use': in_use,
|
||||
'reserved': 0, 'remains': remains}
|
||||
return result
|
||||
|
||||
def fake_get_user_quotas(context, resources, project_id, user_id,
|
||||
quota_class=None, defaults=True,
|
||||
usages=True):
|
||||
self.calls.append('get_user_quotas')
|
||||
result = {}
|
||||
for k, v in resources.items():
|
||||
if k == 'instances':
|
||||
in_use = 1
|
||||
else:
|
||||
in_use = 0
|
||||
result[k] = {'limit': v.default,
|
||||
'in_use': in_use, 'reserved': 0}
|
||||
return result
|
||||
|
||||
def fake_qgabpau(context, project_id, user_id):
|
||||
self.calls.append('quota_get_all_by_project_and_user')
|
||||
return {'instances': 2}
|
||||
|
||||
self.stubs.Set(self.driver, 'get_project_quotas',
|
||||
fake_get_project_quotas)
|
||||
self.stubs.Set(self.driver, 'get_user_quotas',
|
||||
fake_get_user_quotas)
|
||||
self.stubs.Set(db, 'quota_get_all_by_project_and_user',
|
||||
fake_qgabpau)
|
||||
|
||||
def test_get_settable_quotas_with_user(self):
|
||||
self._stub_get_settable_quotas()
|
||||
result = self.driver.get_settable_quotas(
|
||||
FakeContext('test_project', 'test_class'),
|
||||
quota.QUOTAS._resources, 'test_project', user_id='test_user')
|
||||
|
||||
self.assertEqual(self.calls, [
|
||||
'get_project_quotas',
|
||||
'get_user_quotas',
|
||||
'quota_get_all_by_project_and_user',
|
||||
])
|
||||
self.assertEqual(result, {
|
||||
'instances': {
|
||||
'minimum': 1,
|
||||
'maximum': 7,
|
||||
},
|
||||
'cores': {
|
||||
'minimum': 0,
|
||||
'maximum': 20,
|
||||
},
|
||||
'ram': {
|
||||
'minimum': 0,
|
||||
'maximum': 50 * 1024,
|
||||
},
|
||||
'floating_ips': {
|
||||
'minimum': 0,
|
||||
'maximum': 10,
|
||||
},
|
||||
'fixed_ips': {
|
||||
'minimum': 0,
|
||||
'maximum': 10,
|
||||
},
|
||||
'metadata_items': {
|
||||
'minimum': 0,
|
||||
'maximum': 128,
|
||||
},
|
||||
'injected_files': {
|
||||
'minimum': 0,
|
||||
'maximum': 5,
|
||||
},
|
||||
'injected_file_content_bytes': {
|
||||
'minimum': 0,
|
||||
'maximum': 10 * 1024,
|
||||
},
|
||||
'injected_file_path_bytes': {
|
||||
'minimum': 0,
|
||||
'maximum': 255,
|
||||
},
|
||||
'security_groups': {
|
||||
'minimum': 0,
|
||||
'maximum': 10,
|
||||
},
|
||||
'security_group_rules': {
|
||||
'minimum': 0,
|
||||
'maximum': 20,
|
||||
},
|
||||
'key_pairs': {
|
||||
'minimum': 0,
|
||||
'maximum': 100,
|
||||
},
|
||||
})
|
||||
|
||||
def test_get_settable_quotas_without_user(self):
|
||||
self._stub_get_settable_quotas()
|
||||
result = self.driver.get_settable_quotas(
|
||||
FakeContext('test_project', 'test_class'),
|
||||
quota.QUOTAS._resources, 'test_project')
|
||||
|
||||
self.assertEqual(self.calls, [
|
||||
'get_project_quotas',
|
||||
])
|
||||
self.assertEqual(result, {
|
||||
'instances': {
|
||||
'minimum': 5,
|
||||
'maximum': -1,
|
||||
},
|
||||
'cores': {
|
||||
'minimum': 0,
|
||||
'maximum': -1,
|
||||
},
|
||||
'ram': {
|
||||
'minimum': 0,
|
||||
'maximum': -1,
|
||||
},
|
||||
'floating_ips': {
|
||||
'minimum': 0,
|
||||
'maximum': -1,
|
||||
},
|
||||
'fixed_ips': {
|
||||
'minimum': 0,
|
||||
'maximum': -1,
|
||||
},
|
||||
'metadata_items': {
|
||||
'minimum': 0,
|
||||
'maximum': -1,
|
||||
},
|
||||
'injected_files': {
|
||||
'minimum': 0,
|
||||
'maximum': -1,
|
||||
},
|
||||
'injected_file_content_bytes': {
|
||||
'minimum': 0,
|
||||
'maximum': -1,
|
||||
},
|
||||
'injected_file_path_bytes': {
|
||||
'minimum': 0,
|
||||
'maximum': -1,
|
||||
},
|
||||
'security_groups': {
|
||||
'minimum': 0,
|
||||
'maximum': -1,
|
||||
},
|
||||
'security_group_rules': {
|
||||
'minimum': 0,
|
||||
'maximum': -1,
|
||||
},
|
||||
'key_pairs': {
|
||||
'minimum': 0,
|
||||
'maximum': -1,
|
||||
},
|
||||
})
|
||||
|
||||
def _stub_get_project_quotas(self):
|
||||
def fake_get_project_quotas(context, resources, project_id,
|
||||
quota_class=None, defaults=True,
|
||||
|
Loading…
Reference in New Issue
Block a user