summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAarti Kriplani <aarti.kriplani@RACKSPACE.COM>2013-04-22 12:01:27 -0500
committerAarti Kriplani <aarti.kriplani@RACKSPACE.COM>2013-05-23 16:25:29 +0530
commitcdd998c418edc42a6a828ddef144e8408c206b7c (patch)
tree9f23c9005dd304e23acb32ff207bd4c526406e94
parentaf7048590dac77806dd3e7c97a736fda52c2389b (diff)
downloadnova-cdd998c418edc42a6a828ddef144e8408c206b7c.tar.gz
nova-cdd998c418edc42a6a828ddef144e8408c206b7c.tar.xz
nova-cdd998c418edc42a6a828ddef144e8408c206b7c.zip
Delete a quota through admin api.
Added 'extended-quotas' extension that has provides ability for admins to be able to delete a non-default quota (absolute limit) for a tenant, so that tenant's quota will revert back to the configured default. Implements blueprint admin-api-for-delete-quota Change-Id: I7375420a466823b3e099aebff71a8f7d7f922afb
-rw-r--r--doc/api_samples/all_extensions/extensions-get-resp.json8
-rw-r--r--doc/api_samples/all_extensions/extensions-get-resp.xml3
-rw-r--r--etc/nova/policy.json1
-rw-r--r--nova/api/openstack/compute/contrib/extended_quotas.py25
-rw-r--r--nova/api/openstack/compute/contrib/quotas.py18
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_quotas.py33
-rw-r--r--nova/tests/api/openstack/compute/test_extensions.py1
-rw-r--r--nova/tests/fake_policy.py1
-rw-r--r--nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.json.tpl8
-rw-r--r--nova/tests/integrated/api_samples/all_extensions/extensions-get-resp.xml.tpl3
-rw-r--r--nova/tests/integrated/test_api_samples.py16
11 files changed, 115 insertions, 2 deletions
diff --git a/doc/api_samples/all_extensions/extensions-get-resp.json b/doc/api_samples/all_extensions/extensions-get-resp.json
index d7c2a646c..0b587a6b1 100644
--- a/doc/api_samples/all_extensions/extensions-get-resp.json
+++ b/doc/api_samples/all_extensions/extensions-get-resp.json
@@ -409,6 +409,14 @@
"updated": "2012-03-12T00:00:00+00:00"
},
{
+ "alias": "os-extended-quotas",
+ "description": "Adds ability for admins to delete quota",
+ "links": [],
+ "name": "ExtendedQuotas",
+ "namespace": "http://docs.openstack.org/compute/ext/quota-delete/api/v1.1",
+ "updated": "2013-05-23T00:00:00+00:00"
+ },
+ {
"alias": "os-quota-sets",
"description": "Quotas management support.",
"links": [],
diff --git a/doc/api_samples/all_extensions/extensions-get-resp.xml b/doc/api_samples/all_extensions/extensions-get-resp.xml
index f6213a3a9..9924a188a 100644
--- a/doc/api_samples/all_extensions/extensions-get-resp.xml
+++ b/doc/api_samples/all_extensions/extensions-get-resp.xml
@@ -171,6 +171,9 @@
<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>
<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>
</extension>
diff --git a/etc/nova/policy.json b/etc/nova/policy.json
index 26a227ae2..d6524b6a2 100644
--- a/etc/nova/policy.json
+++ b/etc/nova/policy.json
@@ -80,6 +80,7 @@
"compute_extension:networks_associate": "rule:admin_api",
"compute_extension:quotas:show": "",
"compute_extension:quotas:update": "rule:admin_api",
+ "compute_extension:quotas:delete": "rule:admin_api",
"compute_extension:quota_classes": "",
"compute_extension:rescue": "",
"compute_extension:security_group_default_rules": "rule:admin_api",
diff --git a/nova/api/openstack/compute/contrib/extended_quotas.py b/nova/api/openstack/compute/contrib/extended_quotas.py
new file mode 100644
index 000000000..431b95e9b
--- /dev/null
+++ b/nova/api/openstack/compute/contrib/extended_quotas.py
@@ -0,0 +1,25 @@
+# Copyright 2013 Rackspace Hosting
+# 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 import extensions
+
+
+class Extended_quotas(extensions.ExtensionDescriptor):
+ """Adds ability for admins to delete quota."""
+
+ 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"
diff --git a/nova/api/openstack/compute/contrib/quotas.py b/nova/api/openstack/compute/contrib/quotas.py
index c7fe87a1f..0a2453038 100644
--- a/nova/api/openstack/compute/contrib/quotas.py
+++ b/nova/api/openstack/compute/contrib/quotas.py
@@ -33,6 +33,7 @@ LOG = logging.getLogger(__name__)
authorize_update = extensions.extension_authorizer('compute', 'quotas:update')
authorize_show = extensions.extension_authorizer('compute', 'quotas:show')
+authorize_delete = extensions.extension_authorizer('compute', 'quotas:delete')
class QuotaTemplate(xmlutil.TemplateBuilder):
@@ -49,6 +50,9 @@ class QuotaTemplate(xmlutil.TemplateBuilder):
class QuotaSetsController(object):
+ def __init__(self, ext_mgr):
+ self.ext_mgr = ext_mgr
+
def _format_quota_set(self, project_id, quota_set):
"""Convert the quota object to a result dict."""
@@ -124,6 +128,18 @@ class QuotaSetsController(object):
authorize_show(context)
return self._format_quota_set(id, QUOTAS.get_defaults(context))
+ def delete(self, req, id):
+ if self.ext_mgr.is_loaded('os-extended-quotas'):
+ context = req.environ['nova.context']
+ authorize_delete(context)
+ try:
+ nova.context.authorize_project_context(context, id)
+ QUOTAS.destroy_all_by_project(context, id)
+ return webob.Response(status_int=202)
+ except exception.NotAuthorized:
+ raise webob.exc.HTTPForbidden()
+ raise webob.exc.HTTPNotFound()
+
class Quotas(extensions.ExtensionDescriptor):
"""Quotas management support."""
@@ -137,7 +153,7 @@ class Quotas(extensions.ExtensionDescriptor):
resources = []
res = extensions.ResourceExtension('os-quota-sets',
- QuotaSetsController(),
+ QuotaSetsController(self.ext_mgr),
member_actions={'defaults': 'GET'})
resources.append(res)
diff --git a/nova/tests/api/openstack/compute/contrib/test_quotas.py b/nova/tests/api/openstack/compute/contrib/test_quotas.py
index c95c41614..4fb337294 100644
--- a/nova/tests/api/openstack/compute/contrib/test_quotas.py
+++ b/nova/tests/api/openstack/compute/contrib/test_quotas.py
@@ -19,7 +19,10 @@ from lxml import etree
import webob
from nova.api.openstack.compute.contrib import quotas
+from nova.api.openstack import extensions
from nova.api.openstack import wsgi
+from nova import context as context_maker
+from nova import quota
from nova import test
from nova.tests.api.openstack import fakes
@@ -37,7 +40,8 @@ class QuotaSetsTest(test.TestCase):
def setUp(self):
super(QuotaSetsTest, self).setUp()
- self.controller = quotas.QuotaSetsController()
+ self.ext_mgr = self.mox.CreateMock(extensions.ExtensionManager)
+ self.controller = quotas.QuotaSetsController(self.ext_mgr)
def test_format_quota_set(self):
raw_quota_set = {
@@ -201,6 +205,33 @@ class QuotaSetsTest(test.TestCase):
res_dict = self.controller.update(req, 'update_me', body)
self.assertEqual(res_dict, expected_resp)
+ def test_delete_quotas_when_extension_not_loaded(self):
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(False)
+ self.mox.ReplayAll()
+ req = fakes.HTTPRequest.blank('/v2/fake4/os-quota-sets/1234')
+ self.assertRaises(webob.exc.HTTPNotFound, self.controller.delete,
+ req, 1234)
+
+ def test_quotas_delete_as_unauthorized_user(self):
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.ReplayAll()
+ req = fakes.HTTPRequest.blank('/v2/fake4/os-quota-sets/1234')
+ self.assertRaises(webob.exc.HTTPForbidden, self.controller.delete,
+ req, 1234)
+
+ def test_quotas_delete_as_admin(self):
+ context = context_maker.get_admin_context()
+ self.req = fakes.HTTPRequest.blank('/v2/fake4/os-quota-sets/1234')
+ self.req.environ['nova.context'] = context
+ self.ext_mgr.is_loaded('os-extended-quotas').AndReturn(True)
+ self.mox.StubOutWithMock(quota.QUOTAS,
+ "destroy_all_by_project")
+ quota.QUOTAS.destroy_all_by_project(context, 1234)
+ self.mox.ReplayAll()
+ res = self.controller.delete(self.req, 1234)
+ self.mox.VerifyAll()
+ self.assertEqual(res.status_int, 202)
+
class QuotaXMLSerializerTest(test.TestCase):
def setUp(self):
diff --git a/nova/tests/api/openstack/compute/test_extensions.py b/nova/tests/api/openstack/compute/test_extensions.py
index 6e400a075..5c3e07a7a 100644
--- a/nova/tests/api/openstack/compute/test_extensions.py
+++ b/nova/tests/api/openstack/compute/test_extensions.py
@@ -195,6 +195,7 @@ class ExtensionControllerTest(ExtensionTestCase):
"MultipleCreate",
"QuotaClasses",
"Quotas",
+ "ExtendedQuotas",
"Rescue",
"SchedulerHints",
"SecurityGroupDefaultRules",
diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py
index 1290ef80b..b30793ac4 100644
--- a/nova/tests/fake_policy.py
+++ b/nova/tests/fake_policy.py
@@ -159,6 +159,7 @@ policy_data = """
"compute_extension:os-tenant-networks": "",
"compute_extension:quotas:show": "",
"compute_extension:quotas:update": "",
+ "compute_extension:quotas:delete": "",
"compute_extension:quota_classes": "",
"compute_extension: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 d559b4890..7a636036a 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
@@ -417,6 +417,14 @@
"updated": "%(timestamp)s"
},
{
+ "alias": "os-extended-quotas",
+ "description": "%(text)s",
+ "links": [],
+ "name": "ExtendedQuotas",
+ "namespace": "http://docs.openstack.org/compute/ext/quota-delete/api/v1.1",
+ "updated": "%(timestamp)s"
+ },
+ {
"alias": "os-quota-sets",
"description": "%(text)s",
"links": [],
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 cc9ae4c02..ee01eb33c 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
@@ -156,6 +156,9 @@
<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">
+ <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">
<description>%(text)s</description>
</extension>
diff --git a/nova/tests/integrated/test_api_samples.py b/nova/tests/integrated/test_api_samples.py
index 9b678ddd3..873719ab6 100644
--- a/nova/tests/integrated/test_api_samples.py
+++ b/nova/tests/integrated/test_api_samples.py
@@ -2277,6 +2277,22 @@ class QuotasSampleXmlTests(QuotasSampleJsonTests):
ctype = "xml"
+class ExtendedQuotasSampleJsonTests(ApiSampleTestBase):
+ extends_name = "nova.api.openstack.compute.contrib.quotas.Quotas"
+ extension_name = ("nova.api.openstack.compute.contrib"
+ ".extended_quotas.Extended_quotas")
+
+ def test_delete_quotas(self):
+ # Get api sample to delete quota.
+ response = self._do_delete('os-quota-sets/fake_tenant')
+ self.assertEqual(response.status, 202)
+ self.assertEqual(response.read(), '')
+
+
+class ExtendedQuotasSampleXmlTests(ExtendedQuotasSampleJsonTests):
+ ctype = "xml"
+
+
class ExtendedIpsSampleJsonTests(ServersSampleBase):
extension_name = ("nova.api.openstack.compute.contrib"
".extended_ips.Extended_ips")