Merge "Fix limits v3 follow API v3 rules"

This commit is contained in:
Jenkins 2013-12-06 07:20:09 +00:00 committed by Gerrit Code Review
commit c5f68b6b75
8 changed files with 43 additions and 235 deletions

View File

@ -1,18 +1,5 @@
{
"limits": {
"absolute": {
"maxImageMeta": 128,
"maxPersonality": 5,
"maxPersonalitySize": 10240,
"maxSecurityGroupRules": 20,
"maxSecurityGroups": 10,
"maxServerMeta": 128,
"maxTotalCores": 20,
"maxTotalFloatingIps": 10,
"maxTotalInstances": 10,
"maxTotalKeypairs": 100,
"maxTotalRAMSize": 51200
},
"rate": [
{
"limit": [

View File

@ -13,17 +13,4 @@
<limit next-available="2013-09-09T13:37:32Z" unit="MINUTE" verb="GET" remaining="3" value="3"/>
</rate>
</rates>
<absolute>
<limit name="maxServerMeta" value="128"/>
<limit name="maxPersonality" value="5"/>
<limit name="maxImageMeta" value="128"/>
<limit name="maxPersonalitySize" value="10240"/>
<limit name="maxSecurityGroupRules" value="20"/>
<limit name="maxTotalKeypairs" value="100"/>
<limit name="maxSecurityGroups" value="10"/>
<limit name="maxTotalCores" value="20"/>
<limit name="maxTotalFloatingIps" value="10"/>
<limit name="maxTotalInstances" value="10"/>
<limit name="maxTotalRAMSize" value="51200"/>
</absolute>
</limits>

View File

@ -61,53 +61,21 @@ class LimitsTemplate(xmlutil.TemplateBuilder):
limit.set('unit', 'unit')
limit.set('next-available', 'next-available')
absolute = xmlutil.SubTemplateElement(root, 'absolute',
selector='absolute')
limit = xmlutil.SubTemplateElement(absolute, 'limit',
selector=xmlutil.get_items)
limit.set('name', 0)
limit.set('value', 1)
return xmlutil.MasterTemplate(root, 1, nsmap=limits_nsmap)
class LimitsController(wsgi.Controller):
"""Controller for accessing limits in the OpenStack API."""
@extensions.expected_errors(())
@wsgi.serializers(xml=LimitsTemplate)
def index(self, req):
"""Return all global and rate limit information."""
context = req.environ['nova.context']
quotas = QUOTAS.get_project_quotas(context, context.project_id,
usages=False)
abs_limits = dict((k, v['limit']) for k, v in quotas.items())
rate_limits = req.environ.get("nova.limits", [])
builder = self._get_view_builder(req)
return builder.build(rate_limits, abs_limits)
def create(self, req, body):
"""Create a new limit."""
raise webob.exc.HTTPNotImplemented()
def delete(self, req, id):
"""Delete the limit."""
raise webob.exc.HTTPNotImplemented()
def detail(self, req):
"""Return limit details."""
raise webob.exc.HTTPNotImplemented()
def show(self, req, id):
"""Show limit information."""
raise webob.exc.HTTPNotImplemented()
def update(self, req, id, body):
"""Update existing limit."""
raise webob.exc.HTTPNotImplemented()
def _get_view_builder(self, req):
return limits_views.ViewBuilder()
builder = limits_views.ViewBuilderV3()
return builder.build(rate_limits)
class Limit(object):

View File

@ -0,0 +1,20 @@
<element name="limits" ns="http://docs.openstack.org/common/api/v1.0"
xmlns="http://relaxng.org/ns/structure/1.0">
<element name="rates">
<zeroOrMore>
<element name="rate">
<attribute name="uri"> <text/> </attribute>
<attribute name="regex"> <text/> </attribute>
<zeroOrMore>
<element name="limit">
<attribute name="value"> <text/> </attribute>
<attribute name="verb"> <text/> </attribute>
<attribute name="remaining"> <text/> </attribute>
<attribute name="unit"> <text/> </attribute>
<attribute name="next-available"> <text/> </attribute>
</element>
</zeroOrMore>
</element>
</zeroOrMore>
</element>
</element>

View File

@ -98,3 +98,10 @@ class ViewBuilder(object):
"unit": rate_limit["unit"],
"next-available": timeutils.isotime(at=next_avail),
}
class ViewBuilderV3(ViewBuilder):
def build(self, rate_limits):
rate_limits = self._build_rate_limits(rate_limits)
return {"limits": {"rate": rate_limits}}

View File

@ -30,7 +30,6 @@ from nova.api.openstack import xmlutil
import nova.context
from nova.openstack.common import jsonutils
from nova import test
from nova.tests.api.openstack import fakes
from nova.tests import matchers
from nova import utils
@ -58,14 +57,6 @@ class BaseLimitTestSuite(test.NoDBTestCase):
super(BaseLimitTestSuite, self).setUp()
self.time = 0.0
self.stubs.Set(limits.Limit, "_get_time", self._get_time)
self.absolute_limits = {}
def stub_get_project_quotas(context, project_id, usages=True):
return dict((k, dict(limit=v))
for k, v in self.absolute_limits.items())
self.stubs.Set(nova.quota.QUOTAS, "get_project_quotas",
stub_get_project_quotas)
def _get_time(self):
"""Return the "time" according to this test suite."""
@ -111,8 +102,7 @@ class LimitsControllerTest(BaseLimitTestSuite):
body = self.controller.index(request)
expected = {
"limits": {
"rate": [],
"absolute": {},
"rate": []
},
}
self.assertEqual(expected, body)
@ -121,15 +111,6 @@ class LimitsControllerTest(BaseLimitTestSuite):
# Test getting limit details in JSON.
request = self._get_index_request()
request = self._populate_limits(request)
self.absolute_limits = {
'ram': 512,
'instances': 5,
'cores': 21,
'key_pairs': 10,
'floating_ips': 10,
'security_groups': 10,
'security_group_rules': 20,
}
body = self.controller.index(request)
expected = {
"limits": {
@ -168,16 +149,7 @@ class LimitsControllerTest(BaseLimitTestSuite):
],
},
],
"absolute": {
"maxTotalRAMSize": 512,
"maxTotalInstances": 5,
"maxTotalCores": 21,
"maxTotalKeypairs": 10,
"maxTotalFloatingIps": 10,
"maxSecurityGroups": 10,
"maxSecurityGroupRules": 20,
},
]
},
}
self.assertEqual(expected, body)
@ -226,90 +198,11 @@ class LimitsControllerTest(BaseLimitTestSuite):
],
},
],
"absolute": {},
]
},
}
self.assertEqual(expected, body)
def _test_index_absolute_limits_json(self, expected):
request = self._get_index_request()
body = self.controller.index(request)
self.assertEqual(expected, body['limits']['absolute'])
def test_index_ignores_extra_absolute_limits_json(self):
self.absolute_limits = {'unknown_limit': 9001}
self._test_index_absolute_limits_json({})
def test_index_absolute_ram_json(self):
self.absolute_limits = {'ram': 1024}
self._test_index_absolute_limits_json({'maxTotalRAMSize': 1024})
def test_index_absolute_cores_json(self):
self.absolute_limits = {'cores': 17}
self._test_index_absolute_limits_json({'maxTotalCores': 17})
def test_index_absolute_instances_json(self):
self.absolute_limits = {'instances': 19}
self._test_index_absolute_limits_json({'maxTotalInstances': 19})
def test_index_absolute_metadata_json(self):
# NOTE: both server metadata and image metadata are overloaded
# into metadata_items
self.absolute_limits = {'metadata_items': 23}
expected = {
'maxServerMeta': 23,
'maxImageMeta': 23,
}
self._test_index_absolute_limits_json(expected)
def test_index_absolute_injected_files(self):
self.absolute_limits = {
'injected_files': 17,
'injected_file_content_bytes': 86753,
}
expected = {
'maxPersonality': 17,
'maxPersonalitySize': 86753,
}
self._test_index_absolute_limits_json(expected)
def test_index_absolute_security_groups(self):
self.absolute_limits = {
'security_groups': 8,
'security_group_rules': 16,
}
expected = {
'maxSecurityGroups': 8,
'maxSecurityGroupRules': 16,
}
self._test_index_absolute_limits_json(expected)
def test_limit_create(self):
req = fakes.HTTPRequestV3.blank('/limits')
self.assertRaises(webob.exc.HTTPNotImplemented, self.controller.create,
req, {})
def test_limit_delete(self):
req = fakes.HTTPRequestV3.blank('/limits')
self.assertRaises(webob.exc.HTTPNotImplemented, self.controller.delete,
req, 1)
def test_limit_detail(self):
req = fakes.HTTPRequestV3.blank('/limits')
self.assertRaises(webob.exc.HTTPNotImplemented, self.controller.detail,
req)
def test_limit_show(self):
req = fakes.HTTPRequestV3.blank('/limits')
self.assertRaises(webob.exc.HTTPNotImplemented, self.controller.show,
req, 1)
def test_limit_update(self):
req = fakes.HTTPRequestV3.blank('/limits')
self.assertRaises(webob.exc.HTTPNotImplemented, self.controller.update,
req, 1, {})
class MockLimiter(limits.Limiter):
pass
@ -862,7 +755,7 @@ class WsgiLimiterProxyTest(BaseLimitTestSuite):
class LimitsViewBuilderTest(test.NoDBTestCase):
def setUp(self):
super(LimitsViewBuilderTest, self).setUp()
self.view_builder = views.limits.ViewBuilder()
self.view_builder = views.limits.ViewBuilderV3()
self.rate_limits = [{"URI": "*",
"regex": ".*",
"value": 10,
@ -877,9 +770,6 @@ class LimitsViewBuilderTest(test.NoDBTestCase):
"remaining": 10,
"unit": "DAY",
"resetTime": 1311272226}]
self.absolute_limits = {"metadata_items": 1,
"injected_files": 5,
"injected_file_content_bytes": 5}
def test_build_limits(self):
expected_limits = {"limits": {
@ -897,23 +787,17 @@ class LimitsViewBuilderTest(test.NoDBTestCase):
"verb": "POST",
"remaining": 10,
"unit": "DAY",
"next-available": "2011-07-21T18:17:06Z"}]}],
"absolute": {"maxServerMeta": 1,
"maxImageMeta": 1,
"maxPersonality": 5,
"maxPersonalitySize": 5}}}
"next-available": "2011-07-21T18:17:06Z"}]}]}}
output = self.view_builder.build(self.rate_limits,
self.absolute_limits)
output = self.view_builder.build(self.rate_limits)
self.assertThat(output, matchers.DictMatches(expected_limits))
def test_build_limits_empty_limits(self):
expected_limits = {"limits": {"rate": [],
"absolute": {}}}
expected_limits = {"limits": {"rate": []}}
abs_limits = {}
rate_limits = []
output = self.view_builder.build(rate_limits, abs_limits)
output = self.view_builder.build(rate_limits)
self.assertThat(output, matchers.DictMatches(expected_limits))
@ -922,8 +806,7 @@ class LimitsXMLSerializationTest(test.NoDBTestCase):
serializer = limits.LimitsTemplate()
fixture = {"limits": {
"rate": [],
"absolute": {}}}
"rate": []}}
output = serializer.serialize(fixture)
has_dec = output.startswith("<?xml version='1.0' encoding='UTF-8'?>")
@ -949,23 +832,11 @@ class LimitsXMLSerializationTest(test.NoDBTestCase):
"verb": "POST",
"remaining": 10,
"unit": "DAY",
"next-available": "2011-12-15T22:42:45Z"}]}],
"absolute": {"maxServerMeta": 1,
"maxImageMeta": 1,
"maxPersonality": 5,
"maxPersonalitySize": 10240}}}
"next-available": "2011-12-15T22:42:45Z"}]}]}}
output = serializer.serialize(fixture)
root = etree.XML(output)
xmlutil.validate_schema(root, 'limits')
#verify absolute limits
absolutes = root.xpath('ns:absolute/ns:limit', namespaces=NS)
self.assertEqual(len(absolutes), 4)
for limit in absolutes:
name = limit.get('name')
value = limit.get('value')
self.assertEqual(value, str(fixture['limits']['absolute'][name]))
xmlutil.validate_schema(root, 'limits', version='v3')
#verify rate limits
rates = root.xpath('ns:rates/ns:rate', namespaces=NS)
@ -985,17 +856,11 @@ class LimitsXMLSerializationTest(test.NoDBTestCase):
def test_index_no_limits(self):
serializer = limits.LimitsTemplate()
fixture = {"limits": {
"rate": [],
"absolute": {}}}
fixture = {"limits": {"rate": []}}
output = serializer.serialize(fixture)
root = etree.XML(output)
xmlutil.validate_schema(root, 'limits')
#verify absolute limits
absolutes = root.xpath('ns:absolute/ns:limit', namespaces=NS)
self.assertEqual(len(absolutes), 0)
xmlutil.validate_schema(root, 'limits', version='v3')
#verify rate limits
rates = root.xpath('ns:rates/ns:rate', namespaces=NS)

View File

@ -1,18 +1,5 @@
{
"limits": {
"absolute": {
"maxImageMeta": 128,
"maxPersonality": 5,
"maxPersonalitySize": 10240,
"maxSecurityGroupRules": 20,
"maxSecurityGroups": 10,
"maxServerMeta": 128,
"maxTotalCores": 20,
"maxTotalFloatingIps": 10,
"maxTotalInstances": 10,
"maxTotalKeypairs": 100,
"maxTotalRAMSize": 51200
},
"rate": [
{
"limit": [

View File

@ -13,17 +13,4 @@
<limit next-available="%(timestamp)s" unit="MINUTE" verb="GET" remaining="3" value="3"/>
</rate>
</rates>
<absolute>
<limit name="maxServerMeta" value="128"/>
<limit name="maxPersonality" value="5"/>
<limit name="maxImageMeta" value="128"/>
<limit name="maxPersonalitySize" value="10240"/>
<limit name="maxSecurityGroupRules" value="20"/>
<limit name="maxTotalKeypairs" value="100"/>
<limit name="maxSecurityGroups" value="10"/>
<limit name="maxTotalCores" value="20"/>
<limit name="maxTotalFloatingIps" value="10"/>
<limit name="maxTotalInstances" value="10"/>
<limit name="maxTotalRAMSize" value="51200"/>
</absolute>
</limits>