diff options
| author | Jenkins <jenkins@review.openstack.org> | 2012-07-13 21:37:30 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2012-07-13 21:37:30 +0000 |
| commit | e1dd00edae03f90682fcc0e0a49f7aac7f76b3c5 (patch) | |
| tree | cfa47daca3f0700da111d446c703cb7f56bbf789 /nova | |
| parent | b63a3e8cbd8fe57d0be119368bf47964543270c2 (diff) | |
| parent | 86e62b52ac04fe933cec0fc21e52a8fe28930949 (diff) | |
Merge "Extension to show usage of limited resources in /limits response."
Diffstat (limited to 'nova')
| -rw-r--r-- | nova/api/openstack/compute/contrib/used_limits.py | 77 | ||||
| -rw-r--r-- | nova/tests/api/openstack/compute/contrib/test_used_limits.py | 125 |
2 files changed, 202 insertions, 0 deletions
diff --git a/nova/api/openstack/compute/contrib/used_limits.py b/nova/api/openstack/compute/contrib/used_limits.py new file mode 100644 index 000000000..2a8d5d468 --- /dev/null +++ b/nova/api/openstack/compute/contrib/used_limits.py @@ -0,0 +1,77 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 OpenStack LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License + +from nova.api.openstack import extensions +from nova.api.openstack import wsgi +from nova.api.openstack import xmlutil +from nova.openstack.common import log as logging +from nova import quota + + +LOG = logging.getLogger(__name__) +QUOTAS = quota.QUOTAS + + +XMLNS = "http://docs.openstack.org/compute/ext/used_limits/api/v1.1" +ALIAS = "os-used-limits" +authorize = extensions.soft_extension_authorizer('compute', 'used_limits') + + +class UsedLimitsTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('limits', selector='limits') + root.set('{%s}usedLimits' % XMLNS, '%s:usedLimits' % ALIAS) + return xmlutil.SlaveTemplate(root, 1, nsmap={ALIAS: XMLNS}) + + +class UsedLimitsController(wsgi.Controller): + + @wsgi.extends + def index(self, req, resp_obj): + resp_obj.attach(xml=UsedLimitsTemplate()) + context = req.environ['nova.context'] + quotas = QUOTAS.get_project_quotas(context, context.project_id, + usages=True) + quota_map = { + 'totalRAMUsed': 'ram', + 'totalCoresUsed': 'cores', + 'totalInstancesUsed': 'instances', + 'totalVolumesUsed': 'volumes', + 'totalVolumeGigabytesUsed': 'gigabytes', + 'totalSecurityGroupsUsed': 'floating_ips', + 'totalKeyPairsUsed': 'key_pairs', + } + used_limits = {} + for display_name, quota in quota_map.iteritems(): + if quota in quotas: + used_limits[display_name] = quotas[quota]['in_use'] + + resp_obj.obj['limits']['absolute'].update(used_limits) + + +class Used_limits(extensions.ExtensionDescriptor): + """Provide data on limited resources that are being used.""" + + name = "Used Limits" + alias = ALIAS + namespace = XMLNS + updated = "2012-07-13T00:00:00+00:00" + + def get_controller_extensions(self): + controller = UsedLimitsController() + limits_ext = extensions.ControllerExtension(self, 'limits', + controller=controller) + return [limits_ext] diff --git a/nova/tests/api/openstack/compute/contrib/test_used_limits.py b/nova/tests/api/openstack/compute/contrib/test_used_limits.py new file mode 100644 index 000000000..3ab814ebb --- /dev/null +++ b/nova/tests/api/openstack/compute/contrib/test_used_limits.py @@ -0,0 +1,125 @@ +# vim: tabstop=5 shiftwidth=4 softtabstop=4 + +# Copyright 2012 OpenStack LLC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from nova.api.openstack.compute.contrib import used_limits +from nova.api.openstack.compute import limits +from nova.api.openstack import wsgi +import nova.context +from nova import quota +from nova import test + + +class FakeRequest(object): + def __init__(self, context): + self.environ = {'nova.context': context} + + +class UsedLimitsTestCase(test.TestCase): + + def setUp(self): + """Run before each test.""" + super(UsedLimitsTestCase, self).setUp() + self.controller = used_limits.UsedLimitsController() + + self.fake_context = nova.context.RequestContext('fake', 'fake') + self.fake_req = FakeRequest(self.fake_context) + + def test_used_limits(self): + obj = { + "limits": { + "rate": [], + "absolute": {}, + }, + } + res = wsgi.ResponseObject(obj) + quota_map = { + 'totalRAMUsed': 'ram', + 'totalCoresUsed': 'cores', + 'totalInstancesUsed': 'instances', + 'totalVolumesUsed': 'volumes', + 'totalVolumeGigabytesUsed': 'gigabytes', + 'totalSecurityGroupsUsed': 'floating_ips', + 'totalKeyPairsUsed': 'key_pairs', + } + limits = {} + for display_name, q in quota_map.iteritems(): + limits[q] = {'limit': 10, 'in_use': 2} + + def stub_get_project_quotas(context, project_id, usages=True): + return limits + self.stubs.Set(quota.QUOTAS, "get_project_quotas", + stub_get_project_quotas) + + self.controller.index(self.fake_req, res) + abs_limits = res.obj['limits']['absolute'] + for used_limit, value in abs_limits.iteritems(): + self.assertEqual(value, limits[quota_map[used_limit]]['in_use']) + + def test_used_ram_added(self): + obj = { + "limits": { + "rate": [], + "absolute": { + "maxTotalRAMSize": 512, + }, + }, + } + res = wsgi.ResponseObject(obj) + + def stub_get_project_quotas(context, project_id, usages=True): + return {'ram': {'limit': 512, 'in_use': 256}} + self.stubs.Set(quota.QUOTAS, "get_project_quotas", + stub_get_project_quotas) + self.controller.index(self.fake_req, res) + abs_limits = res.obj['limits']['absolute'] + self.assertTrue('totalRAMUsed' in abs_limits) + self.assertEqual(abs_limits['totalRAMUsed'], 256) + + def test_no_ram_quota(self): + obj = { + "limits": { + "rate": [], + "absolute": {}, + }, + } + res = wsgi.ResponseObject(obj) + + def stub_get_project_quotas(context, project_id, usages=True): + return {} + self.stubs.Set(quota.QUOTAS, "get_project_quotas", + stub_get_project_quotas) + self.controller.index(self.fake_req, res) + abs_limits = res.obj['limits']['absolute'] + self.assertFalse('totalRAMUsed' in abs_limits) + + def test_used_limits_xmlns(self): + obj = { + "limits": { + "rate": [], + "absolute": {}, + }, + } + res = wsgi.ResponseObject(obj, xml=limits.LimitsTemplate) + res.preserialize('xml') + + def stub_get_project_quotas(context, project_id, usages=True): + return {} + self.stubs.Set(quota.QUOTAS, "get_project_quotas", + stub_get_project_quotas) + self.controller.index(self.fake_req, res) + response = res.serialize(None, 'xml') + self.assertTrue(used_limits.XMLNS in response.body) |
