Lazy load a project quotas's default values

A project quotas's default values should only be retrieved once we know
they are going to be used. This becomes more important with nested
quotas where a get_defaults call may require calling get_project
in Keystone. As part of this change, code was re-arranged to be
more readable by removing three layers of
a.get('x', b.get('y', c.get('z'))), but the underlying behavior
has not been changed.

Change-Id: I3ea3f6810f2834ae8283449d58642e82189671a7
Depends-On: Ibbd6f47c370d8f10c08cba358574b55e3059dcd1
This commit is contained in:
Ryan McNair 2016-02-11 23:01:42 +00:00
parent a63bfeac76
commit 199162ed07
2 changed files with 31 additions and 11 deletions

View File

@ -188,6 +188,7 @@ class DbQuotaDriver(object):
quotas = {}
project_quotas = db.quota_get_all_by_project(context, project_id)
allocated_quotas = None
default_quotas = None
if usages:
project_usages = db.quota_usage_get_all_by_project(context,
project_id)
@ -206,20 +207,22 @@ class DbQuotaDriver(object):
else:
class_quotas = {}
# TODO(mc_nair): change this to be lazy loaded
default_quotas = self.get_defaults(context, resources, project_id)
for resource in resources.values():
# Omit default/quota class values
if not defaults and resource.name not in project_quotas:
continue
quotas[resource.name] = dict(
limit=project_quotas.get(
resource.name,
class_quotas.get(resource.name,
default_quotas[resource.name])),
)
quota_val = project_quotas.get(resource.name)
if quota_val is None:
quota_val = class_quotas.get(resource.name)
if quota_val is None:
# Lazy load the default quotas
if default_quotas is None:
default_quotas = self.get_defaults(
context, resources, project_id)
quota_val = default_quotas[resource.name]
quotas[resource.name] = {'limit': quota_val}
# Include usages if desired. This is optional because one
# internal consumer of this interface wants to access the

View File

@ -1062,6 +1062,24 @@ class DbQuotaDriverTestCase(DbQuotaDriverBaseTestCase):
reserved= 0)
), result)
@mock.patch('cinder.quota.db.quota_get_all_by_project')
@mock.patch('cinder.quota.db.quota_class_get_default')
def test_get_project_quotas_lazy_load_defaults(
self, mock_defaults, mock_quotas):
mock_quotas.return_value = self._default_quotas_non_child
self.driver.get_project_quotas(
FakeContext('test_project', None),
quota.QUOTAS.resources, 'test_project', usages=False)
# Shouldn't load a project's defaults if all the quotas are already
# defined in the DB
self.assertFalse(mock_defaults.called)
mock_quotas.return_value = {}
self.driver.get_project_quotas(
FakeContext('test_project', None),
quota.QUOTAS.resources, 'test_project', usages=False)
self.assertTrue(mock_defaults.called)
def test_get_root_project_with_subprojects_quotas(self):
self._stub_get_by_project()
self._stub_volume_type_get_all()
@ -1170,8 +1188,7 @@ class DbQuotaDriverTestCase(DbQuotaDriverBaseTestCase):
self.assertEqual(['quota_get_all_by_project',
'quota_usage_get_all_by_project',
'quota_class_get_all_by_name',
'quota_class_get_default', ], self.calls)
'quota_class_get_all_by_name'], self.calls)
self.assertEqual(dict(backups=dict(limit=10,
in_use=2,
reserved=0, ),