summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/api_samples/all_extensions/extensions-get-resp.json6
-rw-r--r--doc/api_samples/all_extensions/extensions-get-resp.xml4
-rw-r--r--doc/api_samples/os-extended-quotas/quotas-update-post-req.json6
-rw-r--r--doc/api_samples/os-extended-quotas/quotas-update-post-req.xml5
-rw-r--r--doc/api_samples/os-extended-quotas/quotas-update-post-resp.json16
-rw-r--r--doc/api_samples/os-extended-quotas/quotas-update-post-resp.xml15
-rw-r--r--nova/api/openstack/compute/contrib/extended_quotas.py9
-rw-r--r--nova/api/openstack/compute/contrib/quotas.py71
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_quotas.py103
-rw-r--r--nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl2
-rw-r--r--nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl2
-rw-r--r--nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-req.json.tpl6
-rw-r--r--nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-req.xml.tpl5
-rw-r--r--nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-resp.json.tpl16
-rw-r--r--nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-resp.xml.tpl15
-rw-r--r--nova/tests/integrated/test_api_samples.py9
16 files changed, 267 insertions, 23 deletions
diff --git a/doc/api_samples/all_extensions/extensions-get-resp.json b/doc/api_samples/all_extensions/extensions-get-resp.json
index b4323b097..ba23bad1e 100644
--- a/doc/api_samples/all_extensions/extensions-get-resp.json
+++ b/doc/api_samples/all_extensions/extensions-get-resp.json
@@ -426,11 +426,11 @@
},
{
"alias": "os-extended-quotas",
- "description": "Adds ability for admins to delete quota",
+ "description": "Adds ability for admins to delete quota and optionally force the update Quota command.",
"links": [],
"name": "ExtendedQuotas",
- "namespace": "http://docs.openstack.org/compute/ext/quota-delete/api/v1.1",
- "updated": "2013-05-23T00:00:00+00:00"
+ "namespace": "http://docs.openstack.org/compute/ext/extended_quotas/api/v1.1",
+ "updated": "2013-06-09T00:00:00+00:00"
},
{
"alias": "os-quota-sets",
diff --git a/doc/api_samples/all_extensions/extensions-get-resp.xml b/doc/api_samples/all_extensions/extensions-get-resp.xml
index 26361e719..64e24b9af 100644
--- a/doc/api_samples/all_extensions/extensions-get-resp.xml
+++ b/doc/api_samples/all_extensions/extensions-get-resp.xml
@@ -177,8 +177,8 @@
<extension alias="os-quota-class-sets" updated="2012-03-12T00:00:00+00:00" namespace="http://docs.openstack.org/compute/ext/quota-classes-sets/api/v1.1" name="QuotaClasses">
<description>Quota classes management support.</description>
</extension>
- <extension alias="os-extended-quotas" updated="2013-05-23T00:00:00+00:00" namespace="http://docs.openstack.org/compute/ext/quota-delete/api/v1.1" name="ExtendedQuotas">
- <description>Adds ability for admins to delete quota.</description>
+ <extension alias="os-extended-quotas" updated="2013-06-09T00:00:00+00:00" namespace="http://docs.openstack.org/compute/ext/extended_quotas/api/v1.1" name="ExtendedQuotas">
+ <description>Adds ability for admins to delete quota and optionally force the update Quota command.</description>
</extension>
<extension alias="os-quota-sets" updated="2011-08-08T00:00:00+00:00" namespace="http://docs.openstack.org/compute/ext/quotas-sets/api/v1.1" name="Quotas">
<description>Quotas management support.</description>
diff --git a/doc/api_samples/os-extended-quotas/quotas-update-post-req.json b/doc/api_samples/os-extended-quotas/quotas-update-post-req.json
new file mode 100644
index 000000000..a58a17912
--- /dev/null
+++ b/doc/api_samples/os-extended-quotas/quotas-update-post-req.json
@@ -0,0 +1,6 @@
+{
+ "quota_set": {
+ "force": "True",
+ "instances": 45
+ }
+}
diff --git a/doc/api_samples/os-extended-quotas/quotas-update-post-req.xml b/doc/api_samples/os-extended-quotas/quotas-update-post-req.xml
new file mode 100644
index 000000000..499b890f0
--- /dev/null
+++ b/doc/api_samples/os-extended-quotas/quotas-update-post-req.xml
@@ -0,0 +1,5 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<quota_set id="fake_tenant">
+ <force>True</force>
+ <instances>45</instances>
+</quota_set> \ No newline at end of file
diff --git a/doc/api_samples/os-extended-quotas/quotas-update-post-resp.json b/doc/api_samples/os-extended-quotas/quotas-update-post-resp.json
new file mode 100644
index 000000000..d9024b77d
--- /dev/null
+++ b/doc/api_samples/os-extended-quotas/quotas-update-post-resp.json
@@ -0,0 +1,16 @@
+{
+ "quota_set": {
+ "cores": 20,
+ "fixed_ips": -1,
+ "floating_ips": 10,
+ "injected_file_content_bytes": 10240,
+ "injected_file_path_bytes": 255,
+ "injected_files": 5,
+ "instances": 45,
+ "key_pairs": 100,
+ "metadata_items": 128,
+ "ram": 51200,
+ "security_group_rules": 20,
+ "security_groups": 10
+ }
+}
diff --git a/doc/api_samples/os-extended-quotas/quotas-update-post-resp.xml b/doc/api_samples/os-extended-quotas/quotas-update-post-resp.xml
new file mode 100644
index 000000000..cd1b80ba0
--- /dev/null
+++ b/doc/api_samples/os-extended-quotas/quotas-update-post-resp.xml
@@ -0,0 +1,15 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<quota_set>
+ <cores>20</cores>
+ <fixed_ips>-1</fixed_ips>
+ <floating_ips>10</floating_ips>
+ <injected_file_content_bytes>10240</injected_file_content_bytes>
+ <injected_file_path_bytes>255</injected_file_path_bytes>
+ <injected_files>5</injected_files>
+ <instances>45</instances>
+ <key_pairs>100</key_pairs>
+ <metadata_items>128</metadata_items>
+ <ram>51200</ram>
+ <security_group_rules>20</security_group_rules>
+ <security_groups>10</security_groups>
+</quota_set>
diff --git a/nova/api/openstack/compute/contrib/extended_quotas.py b/nova/api/openstack/compute/contrib/extended_quotas.py
index 431b95e9b..a21888c4a 100644
--- a/nova/api/openstack/compute/contrib/extended_quotas.py
+++ b/nova/api/openstack/compute/contrib/extended_quotas.py
@@ -17,9 +17,12 @@ from nova.api.openstack import extensions
class Extended_quotas(extensions.ExtensionDescriptor):
- """Adds ability for admins to delete quota."""
+ """Adds ability for admins to delete quota
+ and optionally force the update Quota command.
+ """
name = "ExtendedQuotas"
alias = "os-extended-quotas"
- namespace = "http://docs.openstack.org/compute/ext/quota-delete/api/v1.1"
- updated = "2013-05-23T00:00:00+00:00"
+ namespace = ("http://docs.openstack.org/compute/ext/extended_quotas"
+ "/api/v1.1")
+ updated = "2013-06-09T00:00:00+00:00"
diff --git a/nova/api/openstack/compute/contrib/quotas.py b/nova/api/openstack/compute/contrib/quotas.py
index 0a2453038..a0740ebe5 100644
--- a/nova/api/openstack/compute/contrib/quotas.py
+++ b/nova/api/openstack/compute/contrib/quotas.py
@@ -24,11 +24,13 @@ import nova.context
from nova import db
from nova import exception
from nova.openstack.common import log as logging
+from nova.openstack.common import strutils
from nova import quota
QUOTAS = quota.QUOTAS
LOG = logging.getLogger(__name__)
+NON_QUOTA_KEYS = ['tenant_id', 'id', 'force']
authorize_update = extensions.extension_authorizer('compute', 'quotas:update')
@@ -94,26 +96,71 @@ class QuotaSetsController(object):
project_id = id
bad_keys = []
- for key in body['quota_set'].keys():
+
+ # By default, we can force update the quota if the extended
+ # is not loaded
+ force_update = True
+ extended_loaded = False
+ if self.ext_mgr.is_loaded('os-extended-quotas'):
+ # force optional has been enabled, the default value of
+ # force_update need to be changed to False
+ extended_loaded = True
+ force_update = False
+
+ for key, value in body['quota_set'].items():
if (key not in QUOTAS and
- key != 'tenant_id' and
- key != 'id'):
+ key not in NON_QUOTA_KEYS):
bad_keys.append(key)
+ continue
+ if key == 'force' and extended_loaded:
+ # only check the force optional when the extended has
+ # been loaded
+ force_update = strutils.bool_from_string(value)
+ elif key not in NON_QUOTA_KEYS and value:
+ try:
+ value = int(value)
+ except (ValueError, TypeError):
+ msg = _("Quota '%(value)s' for %(key)s should be "
+ "integer.") % locals()
+ LOG.warn(msg)
+ raise webob.exc.HTTPBadRequest(explanation=msg)
+ self._validate_quota_limit(value)
+
+ LOG.debug(_("force update quotas: %s") % force_update)
if len(bad_keys) > 0:
msg = _("Bad key(s) %s in quota_set") % ",".join(bad_keys)
raise webob.exc.HTTPBadRequest(explanation=msg)
- for key in body['quota_set'].keys():
- try:
- value = int(body['quota_set'][key])
- except (ValueError, TypeError):
- LOG.warn(_("Quota for %s should be integer.") % key)
- # NOTE(hzzhoushaoyu): Do not prevent valid value to be
- # updated. If raise BadRequest, some may be updated and
- # others may be not.
+ try:
+ project_quota = self._get_quotas(context, id, True)
+ except exception.NotAuthorized:
+ raise webob.exc.HTTPForbidden()
+
+ for key, value in body['quota_set'].items():
+ if key in NON_QUOTA_KEYS or not value:
continue
- self._validate_quota_limit(value)
+ # validate whether already used and reserved exceeds the new
+ # quota, this check will be ignored if admin want to force
+ # update
+ value = int(value)
+ if force_update is not True and value >= 0:
+ quota_value = project_quota.get(key)
+ if quota_value and quota_value['limit'] >= 0:
+ quota_used = (quota_value['in_use'] +
+ quota_value['reserved'])
+ LOG.debug(_("Quota %(key)s used: %(quota_used)s, "
+ "value: %(value)s."),
+ {'key': key, 'quota_used': quota_used,
+ 'value': value})
+ if quota_used > value:
+ msg = (_("Quota value %(value)s for %(key)s are "
+ "greater than already used and reserved "
+ "%(quota_used)s") %
+ {'value': value, 'key': key,
+ 'quota_used': quota_used})
+ raise webob.exc.HTTPBadRequest(explanation=msg)
+
try:
db.quota_update(context, project_id, key, value)
except exception.ProjectQuotaNotFound:
diff --git a/nova/tests/api/openstack/compute/contrib/test_quotas.py b/nova/tests/api/openstack/compute/contrib/test_quotas.py
index 4fb337294..979ab3363 100644
--- a/nova/tests/api/openstack/compute/contrib/test_quotas.py
+++ b/nova/tests/api/openstack/compute/contrib/test_quotas.py
@@ -1,6 +1,7 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 OpenStack Foundation
+# Copyright 2013 IBM Corp.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -111,6 +112,8 @@ class QuotaSetsTest(test.TestCase):
req, 1234)
def test_quotas_update_as_admin(self):
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
body = {'quota_set': {'instances': 50, 'cores': 50,
'ram': 51200, 'floating_ips': 10,
'fixed_ips': -1, 'metadata_items': 128,
@@ -128,6 +131,8 @@ class QuotaSetsTest(test.TestCase):
self.assertEqual(res_dict, body)
def test_quotas_update_as_user(self):
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
body = {'quota_set': {'instances': 50, 'cores': 50,
'ram': 51200, 'floating_ips': 10,
'fixed_ips': -1, 'metadata_items': 128,
@@ -142,6 +147,8 @@ class QuotaSetsTest(test.TestCase):
req, 'update_me', body)
def test_quotas_update_invalid_key(self):
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
body = {'quota_set': {'instances2': -2, 'cores': -2,
'ram': -2, 'floating_ips': -2,
'metadata_items': -2, 'injected_files': -2,
@@ -153,6 +160,8 @@ class QuotaSetsTest(test.TestCase):
req, 'update_me', body)
def test_quotas_update_invalid_limit(self):
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
body = {'quota_set': {'instances': -2, 'cores': -2,
'ram': -2, 'floating_ips': -2, 'fixed_ips': -2,
'metadata_items': -2, 'injected_files': -2,
@@ -163,7 +172,7 @@ class QuotaSetsTest(test.TestCase):
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
req, 'update_me', body)
- def test_quotas_update_invalid_value(self):
+ def test_quotas_update_invalid_value_json_fromat_empty_string(self):
expected_resp = {'quota_set': {
'instances': 50, 'cores': 50,
'ram': 51200, 'floating_ips': 10,
@@ -187,9 +196,22 @@ class QuotaSetsTest(test.TestCase):
'key_pairs': 100}}
req = fakes.HTTPRequest.blank('/v2/fake4/os-quota-sets/update_me',
use_admin_context=True)
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
res_dict = self.controller.update(req, 'update_me', body)
self.assertEqual(res_dict, expected_resp)
+ def test_quotas_update_invalid_value_xml_fromat_empty_string(self):
+ expected_resp = {'quota_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}}
# when PUT XML format with empty string for quota
body = {'quota_set': {'instances': 50, 'cores': 50,
'ram': {}, 'floating_ips': 10,
@@ -202,9 +224,29 @@ class QuotaSetsTest(test.TestCase):
'key_pairs': 100}}
req = fakes.HTTPRequest.blank('/v2/fake4/os-quota-sets/update_me',
use_admin_context=True)
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
res_dict = self.controller.update(req, 'update_me', body)
self.assertEqual(res_dict, expected_resp)
+ def test_quotas_update_invalid_value_non_int(self):
+ # when PUT non integer value
+ body = {'quota_set': {'instances': test, 'cores': 50,
+ 'ram': {}, '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-sets/update_me',
+ use_admin_context=True)
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+ self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+ req, 'update_me', body)
+
def test_delete_quotas_when_extension_not_loaded(self):
self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(False)
self.mox.ReplayAll()
@@ -296,3 +338,62 @@ class QuotaXMLSerializerTest(test.TestCase):
result = self.deserializer.deserialize(intext)['body']
self.assertEqual(result, exemplar)
+
+
+fake_quotas = {'ram': {'limit': 51200,
+ 'in_use': 12800,
+ 'reserved': 12800},
+ 'cores': {'limit': 20,
+ 'in_use': 10,
+ 'reserved': 5},
+ 'instances': {'limit': 100,
+ 'in_use': 0,
+ 'reserved': 0}}
+
+
+def fake_get_quotas(self, context, id, usages=False):
+ if usages:
+ return fake_quotas
+ else:
+ return dict((k, v['limit']) for k, v in fake_quotas.items())
+
+
+class ExtendedQuotasTest(test.TestCase):
+
+ def setUp(self):
+ super(ExtendedQuotasTest, self).setUp()
+ self.ext_mgr = self.mox.CreateMock(extensions.ExtensionManager)
+ self.controller = quotas.QuotaSetsController(self.ext_mgr)
+
+ def test_quotas_update_exceed_in_used(self):
+
+ body = {'quota_set': {'cores': 10}}
+
+ self.stubs.Set(quotas.QuotaSetsController, '_get_quotas',
+ fake_get_quotas)
+ req = fakes.HTTPRequest.blank('/v2/fake4/os-quota-sets/update_me',
+ use_admin_context=True)
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+
+ self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
+ req, 'update_me', body)
+
+ def test_quotas_force_update_exceed_in_used(self):
+ self.stubs.Set(quotas.QuotaSetsController, '_get_quotas',
+ fake_get_quotas)
+ req = fakes.HTTPRequest.blank('/v2/fake4/os-quota-sets/update_me',
+ use_admin_context=True)
+ expected = {'quota_set': {'ram': 25600, 'instances': 200, 'cores': 10}}
+ body = {'quota_set': {'ram': 25600,
+ 'instances': 200,
+ 'cores': 10,
+ 'force': 'True'}}
+ fake_quotas.get('ram')['limit'] = 25600
+ fake_quotas.get('cores')['limit'] = 10
+ fake_quotas.get('instances')['limit'] = 200
+
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+ res_dict = self.controller.update(req, 'update_me', body)
+ self.assertEqual(res_dict, expected)
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 0ce9829a7..d1a24d43d 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
@@ -437,7 +437,7 @@
"description": "%(text)s",
"links": [],
"name": "ExtendedQuotas",
- "namespace": "http://docs.openstack.org/compute/ext/quota-delete/api/v1.1",
+ "namespace": "http://docs.openstack.org/compute/ext/extended_quotas/api/v1.1",
"updated": "%(timestamp)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 9f3199418..3fcb59cc9 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
@@ -162,7 +162,7 @@
<extension alias="os-quota-class-sets" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/quota-classes-sets/api/v1.1" name="QuotaClasses">
<description>%(text)s</description>
</extension>
- <extension alias="os-extended-quotas" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/quota-delete/api/v1.1" name="ExtendedQuotas">
+ <extension alias="os-extended-quotas" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/extended_quotas/api/v1.1" name="ExtendedQuotas">
<description>%(text)s</description>
</extension>
<extension alias="os-quota-sets" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/quotas-sets/api/v1.1" name="Quotas">
diff --git a/nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-req.json.tpl b/nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-req.json.tpl
new file mode 100644
index 000000000..a58a17912
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-req.json.tpl
@@ -0,0 +1,6 @@
+{
+ "quota_set": {
+ "force": "True",
+ "instances": 45
+ }
+}
diff --git a/nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-req.xml.tpl b/nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-req.xml.tpl
new file mode 100644
index 000000000..499b890f0
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-req.xml.tpl
@@ -0,0 +1,5 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<quota_set id="fake_tenant">
+ <force>True</force>
+ <instances>45</instances>
+</quota_set> \ No newline at end of file
diff --git a/nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-resp.json.tpl b/nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-resp.json.tpl
new file mode 100644
index 000000000..c882a8cb1
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-resp.json.tpl
@@ -0,0 +1,16 @@
+{
+ "quota_set": {
+ "cores": 20,
+ "floating_ips": 10,
+ "fixed_ips": -1,
+ "injected_file_content_bytes": 10240,
+ "injected_file_path_bytes": 255,
+ "injected_files": 5,
+ "instances": 45,
+ "key_pairs": 100,
+ "metadata_items": 128,
+ "ram": 51200,
+ "security_group_rules": 20,
+ "security_groups": 10
+ }
+}
diff --git a/nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-resp.xml.tpl b/nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-resp.xml.tpl
new file mode 100644
index 000000000..b8c4c0d83
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-extended-quotas/quotas-update-post-resp.xml.tpl
@@ -0,0 +1,15 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<quota_set>
+ <cores>20</cores>
+ <floating_ips>10</floating_ips>
+ <fixed_ips>-1</fixed_ips>
+ <injected_file_content_bytes>10240</injected_file_content_bytes>
+ <injected_file_path_bytes>255</injected_file_path_bytes>
+ <injected_files>5</injected_files>
+ <instances>45</instances>
+ <key_pairs>100</key_pairs>
+ <metadata_items>128</metadata_items>
+ <ram>51200</ram>
+ <security_group_rules>20</security_group_rules>
+ <security_groups>10</security_groups>
+</quota_set>
diff --git a/nova/tests/integrated/test_api_samples.py b/nova/tests/integrated/test_api_samples.py
index 7ac0d2633..bf0b73d6a 100644
--- a/nova/tests/integrated/test_api_samples.py
+++ b/nova/tests/integrated/test_api_samples.py
@@ -1,5 +1,6 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Nebula, Inc.
+# Copyright 2013 IBM Corp.
#
# 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
@@ -2292,6 +2293,14 @@ class ExtendedQuotasSampleJsonTests(ApiSampleTestBase):
self.assertEqual(response.status, 202)
self.assertEqual(response.read(), '')
+ def test_update_quotas(self):
+ # Get api sample to update quotas.
+ response = self._do_put('os-quota-sets/fake_tenant',
+ 'quotas-update-post-req',
+ {})
+ return self._verify_response('quotas-update-post-resp', {},
+ response, 200)
+
class ExtendedQuotasSampleXmlTests(ExtendedQuotasSampleJsonTests):
ctype = "xml"