Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions neutron/db/quota/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,12 @@ def get_detailed_project_quotas(self, context, resources, project_id):
# pass it regardless to keep the quota driver API intact
plugins = directory.get_plugins()
plugin = plugins.get(key, plugins[constants.CORE])
used = resource.count(context, plugin, project_id)
try:
used = resource.count(context, plugin, project_id)
except NotImplementedError:
LOG.info('Skipping quota resource %s: no plugin loaded '
'that supports counting it.', key)
continue

project_quota_ext[key] = {
'limit': resource.default,
Expand All @@ -108,7 +113,8 @@ def get_detailed_project_quotas(self, context, resources, project_id):
quota_objs = quota_obj.Quota.get_objects(context,
project_id=project_id)
for item in quota_objs:
project_quota_ext[item['resource']]['limit'] = item['limit']
if item['resource'] in project_quota_ext:
project_quota_ext[item['resource']]['limit'] = item['limit']
return project_quota_ext

@staticmethod
Expand Down
22 changes: 22 additions & 0 deletions neutron/tests/unit/db/quota/test_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,28 @@ def test_get_detailed_project_quotas_multiple_resource(self):
self.assertEqual(7, detailed_quota[self.resource_2]['reserved'])
self.assertEqual(3, detailed_quota[self.resource_2]['used'])

def test_get_detailed_project_quotas_skips_uncount_resource(self):
def _raise_not_implemented(context, resource, project_id):
raise NotImplementedError(
'No plugins that support counting %s found.' % resource)

resources = {
self.resource_1:
TestTrackedResource(self.resource_1, test_quota.MehModel),
self.resource_2:
TestCountableResource(self.resource_2,
_raise_not_implemented)}
self.plugin.update_quota_limit(self.context, self.project_1,
self.resource_1, 6)
self.plugin.update_quota_limit(self.context, self.project_1,
self.resource_2, 9)
detailed_quota = self.plugin.get_detailed_project_quotas(
self.context, resources, self.project_1)

self.assertIn(self.resource_1, detailed_quota)
self.assertNotIn(self.resource_2, detailed_quota)
self.assertEqual(6, detailed_quota[self.resource_1]['limit'])

def test_quota_limit_check(self):
resources = self._create_resources()
self.plugin.update_quota_limit(self.context, self.project_1,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
fixes:
- |
Fixed a 500 Internal Server Error when querying the quota details API
(``GET /v2.0/quotas/{project_id}/details``) while a service plugin
package (e.g. ``neutron-fwaas``, ``neutron-vpnaas``,
``networking-sfc``) is installed but its service plugin is not
configured in ``service_plugins``. The quota engine now gracefully
skips resources whose service plugin is not loaded instead of raising
a ``NotImplementedError``.