From 35338d54ad2f76807011a5b666df434eec5369b2 Mon Sep 17 00:00:00 2001 From: Matt Riedemann Date: Thu, 29 May 2014 08:21:27 -0700 Subject: [PATCH] Revert "Remove broken quota-classes API" This reverts commit 7d22153d05c67bb0bf4838efdb17b3360ec2e367. The quota_classes API was used to set default quota values so it shouldn't have been removed, so reverting a series of changes that removed the API and it's internal code. Related mailing list thread on the topic: http://lists.openstack.org/pipermail/openstack-dev/2014-May/035383.html Partial-Bug: #1299517 Conflicts: doc/api_samples/all_extensions/extensions-get-resp.json doc/api_samples/all_extensions/extensions-get-resp.xml nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl The conflicts are due to Mark McLoughlin's timestamp-format series of changes on master (Juno). Also note that quota_classes.py was changed due to commit c75a15a4 to rename the NotAuthorized exception to Forbidden. Change-Id: I7890e6b41d4ebf19944c1d4db65111fcc4c45463 --- .../all_extensions/extensions-get-resp.json | 10 +- .../all_extensions/extensions-get-resp.xml | 5 +- .../quota-classes-show-get-resp.json | 17 ++ .../quota-classes-show-get-resp.xml | 15 ++ .../quota-classes-update-post-req.json | 15 ++ .../quota-classes-update-post-req.xml | 14 ++ .../quota-classes-update-post-resp.json | 16 ++ .../quota-classes-update-post-resp.xml | 15 ++ etc/nova/policy.json | 1 + .../compute/contrib/quota_classes.py | 115 +++++++++ .../compute/contrib/test_quota_classes.py | 219 ++++++++++++++++++ .../api/openstack/compute/test_extensions.py | 1 + nova/tests/fake_policy.py | 1 + .../extensions-get-resp.json.tpl | 8 + .../extensions-get-resp.xml.tpl | 3 + .../quota-classes-show-get-resp.json.tpl | 17 ++ .../quota-classes-show-get-resp.xml.tpl | 15 ++ .../quota-classes-update-post-req.json.tpl | 16 ++ .../quota-classes-update-post-req.xml.tpl | 15 ++ .../quota-classes-update-post-resp.json.tpl | 16 ++ .../quota-classes-update-post-resp.xml.tpl | 15 ++ nova/tests/integrated/test_api_samples.py | 25 ++ 22 files changed, 572 insertions(+), 2 deletions(-) create mode 100644 doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json create mode 100644 doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml create mode 100644 doc/api_samples/os-quota-class-sets/quota-classes-update-post-req.json create mode 100644 doc/api_samples/os-quota-class-sets/quota-classes-update-post-req.xml create mode 100644 doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json create mode 100644 doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml create mode 100644 nova/api/openstack/compute/contrib/quota_classes.py create mode 100644 nova/tests/api/openstack/compute/contrib/test_quota_classes.py create mode 100644 nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json.tpl create mode 100644 nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml.tpl create mode 100644 nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.json.tpl create mode 100644 nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.xml.tpl create mode 100644 nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json.tpl create mode 100644 nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml.tpl diff --git a/doc/api_samples/all_extensions/extensions-get-resp.json b/doc/api_samples/all_extensions/extensions-get-resp.json index cc1afaac76d5..99229da36bbe 100644 --- a/doc/api_samples/all_extensions/extensions-get-resp.json +++ b/doc/api_samples/all_extensions/extensions-get-resp.json @@ -504,6 +504,14 @@ "namespace": "http://docs.openstack.org/compute/ext/preserve_ephemeral_rebuild/api/v2", "updated": "2013-12-17T00:00:00Z" }, + { + "alias": "os-quota-class-sets", + "description": "Quota classes management support.", + "links": [], + "name": "QuotaClasses", + "namespace": "http://docs.openstack.org/compute/ext/quota-classes-sets/api/v1.1", + "updated": "2012-03-12T00:00:00Z" + }, { "alias": "os-quota-sets", "description": "Quotas management support.", @@ -665,4 +673,4 @@ "updated": "2011-03-25T00:00:00Z" } ] -} \ No newline at end of file +} diff --git a/doc/api_samples/all_extensions/extensions-get-resp.xml b/doc/api_samples/all_extensions/extensions-get-resp.xml index ffa9ff6bf56b..eb4e6e32d39a 100644 --- a/doc/api_samples/all_extensions/extensions-get-resp.xml +++ b/doc/api_samples/all_extensions/extensions-get-resp.xml @@ -207,6 +207,9 @@ Allow preservation of the ephemeral partition on rebuild. + + Quota classes management support. + Quotas management support. @@ -267,4 +270,4 @@ Volumes support. - \ No newline at end of file + diff --git a/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json b/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json new file mode 100644 index 000000000000..6e477722dda8 --- /dev/null +++ b/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json @@ -0,0 +1,17 @@ +{ + "quota_class_set": { + "cores": 20, + "fixed_ips": -1, + "floating_ips": 10, + "id": "test_class", + "injected_file_content_bytes": 10240, + "injected_file_path_bytes": 255, + "injected_files": 5, + "instances": 10, + "key_pairs": 100, + "metadata_items": 128, + "ram": 51200, + "security_group_rules": 20, + "security_groups": 10 + } +} diff --git a/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml b/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml new file mode 100644 index 000000000000..91929d34ad22 --- /dev/null +++ b/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml @@ -0,0 +1,15 @@ + + + 20 + -1 + 10 + 10240 + 255 + 5 + 10 + 100 + 128 + 51200 + 20 + 10 + diff --git a/doc/api_samples/os-quota-class-sets/quota-classes-update-post-req.json b/doc/api_samples/os-quota-class-sets/quota-classes-update-post-req.json new file mode 100644 index 000000000000..f074c829ffaa --- /dev/null +++ b/doc/api_samples/os-quota-class-sets/quota-classes-update-post-req.json @@ -0,0 +1,15 @@ +{ + "quota_class_set": { + "instances": 50, + "cores": 50, + "ram": 51200, + "floating_ips": 10, + "metadata_items": 128, + "injected_files": 5, + "injected_file_content_bytes": 10240, + "injected_file_path_bytes": 255, + "security_groups": 10, + "security_group_rules": 20, + "key_pairs": 100 + } +} diff --git a/doc/api_samples/os-quota-class-sets/quota-classes-update-post-req.xml b/doc/api_samples/os-quota-class-sets/quota-classes-update-post-req.xml new file mode 100644 index 000000000000..d14785482022 --- /dev/null +++ b/doc/api_samples/os-quota-class-sets/quota-classes-update-post-req.xml @@ -0,0 +1,14 @@ + + + 50 + 10 + 10240 + 255 + 5 + 50 + 100 + 128 + 51200 + 20 + 10 + diff --git a/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json b/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json new file mode 100644 index 000000000000..c86f86063b88 --- /dev/null +++ b/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json @@ -0,0 +1,16 @@ +{ + "quota_class_set": { + "cores": 50, + "fixed_ips": -1, + "floating_ips": 10, + "injected_file_content_bytes": 10240, + "injected_file_path_bytes": 255, + "injected_files": 5, + "instances": 50, + "key_pairs": 100, + "metadata_items": 128, + "ram": 51200, + "security_group_rules": 20, + "security_groups": 10 + } +} diff --git a/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml b/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml new file mode 100644 index 000000000000..23eb5088c763 --- /dev/null +++ b/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml @@ -0,0 +1,15 @@ + + + 50 + -1 + 10 + 10240 + 255 + 5 + 50 + 100 + 128 + 51200 + 20 + 10 + diff --git a/etc/nova/policy.json b/etc/nova/policy.json index a9933f50cd95..538abe111602 100644 --- a/etc/nova/policy.json +++ b/etc/nova/policy.json @@ -201,6 +201,7 @@ "compute_extension:v3:os-quota-sets:update": "rule:admin_api", "compute_extension:v3:os-quota-sets:delete": "rule:admin_api", "compute_extension:v3:os-quota-sets:detail": "rule:admin_api", + "compute_extension:quota_classes": "", "compute_extension:rescue": "", "compute_extension:v3:os-rescue": "", "compute_extension:v3:os-rescue:discoverable": "", diff --git a/nova/api/openstack/compute/contrib/quota_classes.py b/nova/api/openstack/compute/contrib/quota_classes.py new file mode 100644 index 000000000000..755bdefc9c16 --- /dev/null +++ b/nova/api/openstack/compute/contrib/quota_classes.py @@ -0,0 +1,115 @@ +# Copyright 2012 OpenStack Foundation +# 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. + +import webob + +from nova.api.openstack import extensions +from nova.api.openstack import wsgi +from nova.api.openstack import xmlutil +import nova.context +from nova import db +from nova import exception +from nova.openstack.common.gettextutils import _ +from nova import quota +from nova import utils + + +QUOTAS = quota.QUOTAS + + +authorize = extensions.extension_authorizer('compute', 'quota_classes') + + +class QuotaClassTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('quota_class_set', + selector='quota_class_set') + root.set('id') + + for resource in QUOTAS.resources: + elem = xmlutil.SubTemplateElement(root, resource) + elem.text = resource + + return xmlutil.MasterTemplate(root, 1) + + +class QuotaClassSetsController(wsgi.Controller): + + def _format_quota_set(self, quota_class, quota_set): + """Convert the quota object to a result dict.""" + + result = dict(id=str(quota_class)) + + for resource in QUOTAS.resources: + result[resource] = quota_set[resource] + + return dict(quota_class_set=result) + + @wsgi.serializers(xml=QuotaClassTemplate) + def show(self, req, id): + context = req.environ['nova.context'] + authorize(context) + try: + nova.context.authorize_quota_class_context(context, id) + return self._format_quota_set(id, + QUOTAS.get_class_quotas(context, id)) + except exception.Forbidden: + raise webob.exc.HTTPForbidden() + + @wsgi.serializers(xml=QuotaClassTemplate) + def update(self, req, id, body): + context = req.environ['nova.context'] + authorize(context) + quota_class = id + + if not self.is_valid_body(body, 'quota_class_set'): + msg = _("quota_class_set not specified") + raise webob.exc.HTTPBadRequest(explanation=msg) + quota_class_set = body['quota_class_set'] + for key in quota_class_set.keys(): + if key in QUOTAS: + try: + value = utils.validate_integer( + body['quota_class_set'][key], key) + except exception.InvalidInput as e: + raise webob.exc.HTTPBadRequest( + explanation=e.format_message()) + try: + db.quota_class_update(context, quota_class, key, value) + except exception.QuotaClassNotFound: + db.quota_class_create(context, quota_class, key, value) + except exception.AdminRequired: + raise webob.exc.HTTPForbidden() + return {'quota_class_set': QUOTAS.get_class_quotas(context, + quota_class)} + + +class Quota_classes(extensions.ExtensionDescriptor): + """Quota classes management support.""" + + name = "QuotaClasses" + alias = "os-quota-class-sets" + namespace = ("http://docs.openstack.org/compute/ext/" + "quota-classes-sets/api/v1.1") + updated = "2012-03-12T00:00:00Z" + + def get_resources(self): + resources = [] + + res = extensions.ResourceExtension('os-quota-class-sets', + QuotaClassSetsController()) + resources.append(res) + + return resources diff --git a/nova/tests/api/openstack/compute/contrib/test_quota_classes.py b/nova/tests/api/openstack/compute/contrib/test_quota_classes.py new file mode 100644 index 000000000000..998aa2044d15 --- /dev/null +++ b/nova/tests/api/openstack/compute/contrib/test_quota_classes.py @@ -0,0 +1,219 @@ +# Copyright 2012 OpenStack Foundation +# 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 lxml import etree +import webob + +from nova.api.openstack.compute.contrib import quota_classes +from nova.api.openstack import wsgi +from nova import test +from nova.tests.api.openstack import fakes + + +def quota_set(class_name): + return {'quota_class_set': {'id': class_name, 'metadata_items': 128, + 'ram': 51200, 'floating_ips': 10, + 'fixed_ips': -1, 'instances': 10, + 'injected_files': 5, 'cores': 20, + 'injected_file_content_bytes': 10240, + 'security_groups': 10, + 'security_group_rules': 20, 'key_pairs': 100, + 'injected_file_path_bytes': 255}} + + +class QuotaClassSetsTest(test.TestCase): + + def setUp(self): + super(QuotaClassSetsTest, self).setUp() + self.controller = quota_classes.QuotaClassSetsController() + + def test_format_quota_set(self): + raw_quota_set = { + 'instances': 10, + 'cores': 20, + 'ram': 51200, + 'floating_ips': 10, + 'fixed_ips': -1, + 'metadata_items': 128, + 'injected_files': 5, + 'injected_file_path_bytes': 255, + 'injected_file_content_bytes': 10240, + 'security_groups': 10, + 'security_group_rules': 20, + 'key_pairs': 100, + } + + quota_set = self.controller._format_quota_set('test_class', + raw_quota_set) + qs = quota_set['quota_class_set'] + + self.assertEqual(qs['id'], 'test_class') + self.assertEqual(qs['instances'], 10) + self.assertEqual(qs['cores'], 20) + self.assertEqual(qs['ram'], 51200) + self.assertEqual(qs['floating_ips'], 10) + self.assertEqual(qs['fixed_ips'], -1) + self.assertEqual(qs['metadata_items'], 128) + self.assertEqual(qs['injected_files'], 5) + self.assertEqual(qs['injected_file_path_bytes'], 255) + self.assertEqual(qs['injected_file_content_bytes'], 10240) + self.assertEqual(qs['security_groups'], 10) + self.assertEqual(qs['security_group_rules'], 20) + self.assertEqual(qs['key_pairs'], 100) + + def test_quotas_show_as_admin(self): + req = fakes.HTTPRequest.blank( + '/v2/fake4/os-quota-class-sets/test_class', + use_admin_context=True) + res_dict = self.controller.show(req, 'test_class') + + self.assertEqual(res_dict, quota_set('test_class')) + + def test_quotas_show_as_unauthorized_user(self): + req = fakes.HTTPRequest.blank( + '/v2/fake4/os-quota-class-sets/test_class') + self.assertRaises(webob.exc.HTTPForbidden, self.controller.show, + req, 'test_class') + + def test_quotas_update_as_admin(self): + body = {'quota_class_set': {'instances': 50, 'cores': 50, + 'ram': 51200, 'floating_ips': 10, + 'fixed_ips': -1, 'metadata_items': 128, + 'injected_files': 5, + 'injected_file_content_bytes': 10240, + 'injected_file_path_bytes': 255, + 'security_groups': 10, + 'security_group_rules': 20, + 'key_pairs': 100}} + + req = fakes.HTTPRequest.blank( + '/v2/fake4/os-quota-class-sets/test_class', + use_admin_context=True) + res_dict = self.controller.update(req, 'test_class', body) + + self.assertEqual(res_dict, body) + + def test_quotas_update_as_user(self): + body = {'quota_class_set': {'instances': 50, 'cores': 50, + 'ram': 51200, 'floating_ips': 10, + 'fixed_ips': -1, 'metadata_items': 128, + 'injected_files': 5, + 'injected_file_content_bytes': 10240, + 'security_groups': 10, + 'security_group_rules': 20, + 'key_pairs': 100, + }} + + req = fakes.HTTPRequest.blank( + '/v2/fake4/os-quota-class-sets/test_class') + self.assertRaises(webob.exc.HTTPForbidden, self.controller.update, + req, 'test_class', body) + + def test_quotas_update_with_empty_body(self): + body = {} + req = fakes.HTTPRequest.blank( + '/v2/fake4/os-quota-class-sets/test_class', + use_admin_context=True) + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, + req, 'test_class', body) + + def test_quotas_update_with_non_integer(self): + body = {'quota_class_set': {'instances': "abc"}} + req = fakes.HTTPRequest.blank( + '/v2/fake4/os-quota-class-sets/test_class', + use_admin_context=True) + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, + req, 'test_class', body) + + body = {'quota_class_set': {'instances': 50.5}} + req = fakes.HTTPRequest.blank( + '/v2/fake4/os-quota-class-sets/test_class', + use_admin_context=True) + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, + req, 'test_class', body) + + body = {'quota_class_set': { + 'instances': u'\u30aa\u30fc\u30d7\u30f3'}} + req = fakes.HTTPRequest.blank( + '/v2/fake4/os-quota-class-sets/test_class', + use_admin_context=True) + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, + req, 'test_class', body) + + +class QuotaTemplateXMLSerializerTest(test.TestCase): + def setUp(self): + super(QuotaTemplateXMLSerializerTest, self).setUp() + self.serializer = quota_classes.QuotaClassTemplate() + self.deserializer = wsgi.XMLDeserializer() + + def test_serializer(self): + exemplar = dict(quota_class_set=dict( + id='test_class', + metadata_items=10, + injected_file_path_bytes=255, + injected_file_content_bytes=20, + ram=50, + floating_ips=60, + fixed_ips=-1, + instances=70, + injected_files=80, + security_groups=10, + security_group_rules=20, + key_pairs=100, + cores=90)) + text = self.serializer.serialize(exemplar) + + tree = etree.fromstring(text) + + self.assertEqual('quota_class_set', tree.tag) + self.assertEqual('test_class', tree.get('id')) + self.assertEqual(len(exemplar['quota_class_set']) - 1, len(tree)) + for child in tree: + self.assertIn(child.tag, exemplar['quota_class_set']) + self.assertEqual(int(child.text), + exemplar['quota_class_set'][child.tag]) + + def test_deserializer(self): + exemplar = dict(quota_class_set=dict( + metadata_items='10', + injected_file_content_bytes='20', + ram='50', + floating_ips='60', + fixed_ips='-1', + instances='70', + injected_files='80', + security_groups='10', + security_group_rules='20', + key_pairs='100', + cores='90')) + intext = ("\n" + '' + '10' + '20' + '' + '50' + '60' + '-1' + '70' + '80' + '90' + '10' + '20' + '100' + '') + + result = self.deserializer.deserialize(intext)['body'] + self.assertEqual(result, exemplar) diff --git a/nova/tests/api/openstack/compute/test_extensions.py b/nova/tests/api/openstack/compute/test_extensions.py index 975935257e3c..5de7c0091cdb 100644 --- a/nova/tests/api/openstack/compute/test_extensions.py +++ b/nova/tests/api/openstack/compute/test_extensions.py @@ -228,6 +228,7 @@ class ExtensionControllerTest(ExtensionTestCase): "Keypairs", "Multinic", "MultipleCreate", + "QuotaClasses", "Quotas", "ExtendedQuotas", "Rescue", diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py index 3ad3f6a7d5f2..d5179d27ac47 100644 --- a/nova/tests/fake_policy.py +++ b/nova/tests/fake_policy.py @@ -249,6 +249,7 @@ policy_data = """ "compute_extension:v3:os-quota-sets:update": "", "compute_extension:v3:os-quota-sets:delete": "", "compute_extension:v3:os-quota-sets:detail": "", + "compute_extension:quota_classes": "", "compute_extension:rescue": "", "compute_extension:v3:os-rescue": "", "compute_extension:security_group_default_rules": "", diff --git a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl index 75aa72746a57..c4089502250a 100644 --- a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl +++ b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl @@ -472,6 +472,14 @@ "namespace": "http://docs.openstack.org/compute/ext/networks_associate/api/v2", "updated": "%(isotime)s" }, + { + "alias": "os-quota-class-sets", + "description": "%(text)s", + "links": [], + "name": "QuotaClasses", + "namespace": "http://docs.openstack.org/compute/ext/quota-classes-sets/api/v1.1", + "updated": "%(isotime)s" + }, { "alias": "os-extended-quotas", "description": "%(text)s", diff --git a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl index 4d914ed9bf3e..08c9b9f3c88c 100644 --- a/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl +++ b/nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl @@ -168,6 +168,9 @@ %(text)s + + %(text)s + %(text)s diff --git a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json.tpl b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json.tpl new file mode 100644 index 000000000000..f9a94e760af7 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json.tpl @@ -0,0 +1,17 @@ +{ + "quota_class_set": { + "cores": 20, + "floating_ips": 10, + "fixed_ips": -1, + "id": "%(set_id)s", + "injected_file_content_bytes": 10240, + "injected_file_path_bytes": 255, + "injected_files": 5, + "instances": 10, + "key_pairs": 100, + "metadata_items": 128, + "ram": 51200, + "security_group_rules": 20, + "security_groups": 10 + } +} diff --git a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml.tpl b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml.tpl new file mode 100644 index 000000000000..fb8e7992a510 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml.tpl @@ -0,0 +1,15 @@ + + + 20 + 10 + -1 + 10240 + 255 + 5 + 10 + 100 + 128 + 51200 + 20 + 10 + diff --git a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.json.tpl b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.json.tpl new file mode 100644 index 000000000000..483fda8c53e7 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.json.tpl @@ -0,0 +1,16 @@ +{ + "quota_class_set": { + "instances": 50, + "cores": 50, + "ram": 51200, + "floating_ips": 10, + "fixed_ips": -1, + "metadata_items": 128, + "injected_files": 5, + "injected_file_content_bytes": 10240, + "injected_file_path_bytes": 255, + "security_groups": 10, + "security_group_rules": 20, + "key_pairs": 100 + } +} diff --git a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.xml.tpl b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.xml.tpl new file mode 100644 index 000000000000..150fb6a42a7c --- /dev/null +++ b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.xml.tpl @@ -0,0 +1,15 @@ + + + 50 + 10 + -1 + 10240 + 255 + 5 + 50 + 100 + 128 + 51200 + 20 + 10 + diff --git a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json.tpl b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json.tpl new file mode 100644 index 000000000000..c36783f2f0e6 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json.tpl @@ -0,0 +1,16 @@ +{ + "quota_class_set": { + "cores": 50, + "floating_ips": 10, + "fixed_ips": -1, + "injected_file_content_bytes": 10240, + "injected_file_path_bytes": 255, + "injected_files": 5, + "instances": 50, + "key_pairs": 100, + "metadata_items": 128, + "ram": 51200, + "security_group_rules": 20, + "security_groups": 10 + } +} diff --git a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml.tpl b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml.tpl new file mode 100644 index 000000000000..cd674a24dab8 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml.tpl @@ -0,0 +1,15 @@ + + + 50 + 10 + -1 + 10240 + 255 + 5 + 50 + 100 + 128 + 51200 + 20 + 10 + diff --git a/nova/tests/integrated/test_api_samples.py b/nova/tests/integrated/test_api_samples.py index 73fab36c988f..749cee44659a 100644 --- a/nova/tests/integrated/test_api_samples.py +++ b/nova/tests/integrated/test_api_samples.py @@ -2709,6 +2709,31 @@ class FlavorDisabledSampleXmlTests(FlavorDisabledSampleJsonTests): ctype = "xml" +class QuotaClassesSampleJsonTests(ApiSampleTestBaseV2): + extension_name = ("nova.api.openstack.compute.contrib.quota_classes." + "Quota_classes") + set_id = 'test_class' + + def test_show_quota_classes(self): + # Get api sample to show quota classes. + response = self._do_get('os-quota-class-sets/%s' % self.set_id) + subs = {'set_id': self.set_id} + self._verify_response('quota-classes-show-get-resp', subs, + response, 200) + + def test_update_quota_classes(self): + # Get api sample to update quota classes. + response = self._do_put('os-quota-class-sets/%s' % self.set_id, + 'quota-classes-update-post-req', + {}) + self._verify_response('quota-classes-update-post-resp', + {}, response, 200) + + +class QuotaClassesSampleXmlTests(QuotaClassesSampleJsonTests): + ctype = "xml" + + class CellsSampleJsonTest(ApiSampleTestBaseV2): extension_name = "nova.api.openstack.compute.contrib.cells.Cells"