diff options
| author | Brian Waldon <brian.waldon@rackspace.com> | 2011-04-05 14:47:06 -0400 |
|---|---|---|
| committer | Brian Waldon <brian.waldon@rackspace.com> | 2011-04-05 14:47:06 -0400 |
| commit | 24c2da40549e882be716e1897fd81aef8f172e53 (patch) | |
| tree | 75e8f25b561144ed7313156e7d07358a517c62e8 | |
| parent | c0a8904508edb0687b588d40a7bd181d0393884f (diff) | |
adding support for OSAPI v1.1 limits resource
| -rw-r--r-- | nova/api/openstack/__init__.py | 9 | ||||
| -rw-r--r-- | nova/api/openstack/limits.py | 26 | ||||
| -rw-r--r-- | nova/tests/api/openstack/test_limits.py | 121 |
3 files changed, 131 insertions, 25 deletions
diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 7545eb0c9..0e0a0646e 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -111,9 +111,6 @@ class APIRouter(wsgi.Router): parent_resource=dict(member_name='server', collection_name='servers')) - _limits = limits.LimitsController() - mapper.resource("limit", "limits", controller=_limits) - super(APIRouter, self).__init__(mapper) @@ -144,6 +141,9 @@ class APIRouterV10(APIRouter): parent_resource=dict(member_name='server', collection_name='servers')) + mapper.resource("limit", "limits", + controller=limits.LimitsControllerV10()) + class APIRouterV11(APIRouter): """Define routes specific to OpenStack API V1.1.""" @@ -172,3 +172,6 @@ class APIRouterV11(APIRouter): mapper.resource("flavor", "flavors", controller=flavors.ControllerV11(), collection={'detail': 'GET'}) + + mapper.resource("limit", "limits", + controller=limits.LimitsControllerV11()) diff --git a/nova/api/openstack/limits.py b/nova/api/openstack/limits.py index efc7d193d..f9e047e97 100644 --- a/nova/api/openstack/limits.py +++ b/nova/api/openstack/limits.py @@ -32,6 +32,7 @@ from webob.dec import wsgify from nova import wsgi from nova.api.openstack import faults +from nova.api.openstack.views import limits as limits_views from nova.wsgi import Controller from nova.wsgi import Middleware @@ -51,8 +52,8 @@ class LimitsController(Controller): _serialization_metadata = { "application/xml": { "attributes": { - "limit": ["verb", "URI", "regex", "value", "unit", - "resetTime", "remaining", "name"], + "limit": ["verb", "URI", "uri", "regex", "value", "unit", + "resetTime", "next-available", "remaining", "name"], }, "plurals": { "rate": "limit", @@ -67,12 +68,21 @@ class LimitsController(Controller): abs_limits = {} rate_limits = req.environ.get("nova.limits", []) - return { - "limits": { - "rate": rate_limits, - "absolute": abs_limits, - }, - } + builder = self._get_view_builder(req) + return builder.build(rate_limits, abs_limits) + + def _get_view_builder(self, req): + raise NotImplementedError() + + +class LimitsControllerV10(LimitsController): + def _get_view_builder(self, req): + return limits_views.ViewBuilderV10() + + +class LimitsControllerV11(LimitsController): + def _get_view_builder(self, req): + return limits_views.ViewBuilderV11() class Limit(object): diff --git a/nova/tests/api/openstack/test_limits.py b/nova/tests/api/openstack/test_limits.py index 05cfacc60..f557c0599 100644 --- a/nova/tests/api/openstack/test_limits.py +++ b/nova/tests/api/openstack/test_limits.py @@ -28,15 +28,14 @@ import webob from xml.dom.minidom import parseString from nova.api.openstack import limits -from nova.api.openstack.limits import Limit TEST_LIMITS = [ - Limit("GET", "/delayed", "^/delayed", 1, limits.PER_MINUTE), - Limit("POST", "*", ".*", 7, limits.PER_MINUTE), - Limit("POST", "/servers", "^/servers", 3, limits.PER_MINUTE), - Limit("PUT", "*", "", 10, limits.PER_MINUTE), - Limit("PUT", "/servers", "^/servers", 5, limits.PER_MINUTE), + limits.Limit("GET", "/delayed", "^/delayed", 1, limits.PER_MINUTE), + limits.Limit("POST", "*", ".*", 7, limits.PER_MINUTE), + limits.Limit("POST", "/servers", "^/servers", 3, limits.PER_MINUTE), + limits.Limit("PUT", "*", "", 10, limits.PER_MINUTE), + limits.Limit("PUT", "/servers", "^/servers", 5, limits.PER_MINUTE), ] @@ -58,15 +57,15 @@ class BaseLimitTestSuite(unittest.TestCase): return self.time -class LimitsControllerTest(BaseLimitTestSuite): +class LimitsControllerV10Test(BaseLimitTestSuite): """ - Tests for `limits.LimitsController` class. + Tests for `limits.LimitsControllerV10` class. """ def setUp(self): """Run before each test.""" BaseLimitTestSuite.setUp(self) - self.controller = limits.LimitsController() + self.controller = limits.LimitsControllerV10() def _get_index_request(self, accept_header="application/json"): """Helper to set routing arguments.""" @@ -81,8 +80,8 @@ class LimitsControllerTest(BaseLimitTestSuite): def _populate_limits(self, request): """Put limit info into a request.""" _limits = [ - Limit("GET", "*", ".*", 10, 60).display(), - Limit("POST", "*", ".*", 5, 60 * 60).display(), + limits.Limit("GET", "*", ".*", 10, 60).display(), + limits.Limit("POST", "*", ".*", 5, 60 * 60).display(), ] request.environ["nova.limits"] = _limits return request @@ -163,6 +162,100 @@ class LimitsControllerTest(BaseLimitTestSuite): self.assertEqual(expected.toxml(), body.toxml()) +class LimitsControllerV11Test(BaseLimitTestSuite): + """ + Tests for `limits.LimitsControllerV11` class. + """ + + def setUp(self): + """Run before each test.""" + BaseLimitTestSuite.setUp(self) + self.controller = limits.LimitsControllerV11() + + def _get_index_request(self, accept_header="application/json"): + """Helper to set routing arguments.""" + request = webob.Request.blank("/") + request.accept = accept_header + request.environ["wsgiorg.routing_args"] = (None, { + "action": "index", + "controller": "", + }) + return request + + def _populate_limits(self, request): + """Put limit info into a request.""" + _limits = [ + limits.Limit("GET", "*", ".*", 10, 60).display(), + limits.Limit("POST", "*", ".*", 5, 60 * 60).display(), + limits.Limit("GET", "changes-since*", "changes-since", + 5, 60).display(), + ] + request.environ["nova.limits"] = _limits + return request + + def test_empty_index_json(self): + """Test getting empty limit details in JSON.""" + request = self._get_index_request() + response = request.get_response(self.controller) + expected = { + "limits": { + "rate": [], + "absolute": {}, + }, + } + body = json.loads(response.body) + self.assertEqual(expected, body) + + def test_index_json(self): + """Test getting limit details in JSON.""" + request = self._get_index_request() + request = self._populate_limits(request) + response = request.get_response(self.controller) + expected = { + "limits": { + "rate": [ + { + "regex": "changes-since", + "uri": "changes-since*", + "limits": [ + { + "verb": "GET", + "next-available": 0, + "unit": "MINUTE", + "value": 5, + "remaining": 5, + }, + ], + }, + { + "regex": ".*", + "uri": "*", + "limits": [ + { + "verb": "GET", + "next-available": 0, + "unit": "MINUTE", + "value": 10, + "remaining": 10, + }, + { + "verb": "POST", + "next-available": 0, + "unit": "HOUR", + "value": 5, + "remaining": 5, + }, + ], + }, + + ], + "absolute": {}, + }, + } + body = json.loads(response.body) + self.assertEqual(expected, body) + + class LimitMiddlewareTest(BaseLimitTestSuite): """ Tests for the `limits.RateLimitingMiddleware` class. @@ -177,7 +270,7 @@ class LimitMiddlewareTest(BaseLimitTestSuite): """Prepare middleware for use through fake WSGI app.""" BaseLimitTestSuite.setUp(self) _limits = [ - Limit("GET", "*", ".*", 1, 60), + limits.Limit("GET", "*", ".*", 1, 60), ] self.app = limits.RateLimitingMiddleware(self._empty_app, _limits) @@ -230,7 +323,7 @@ class LimitTest(BaseLimitTestSuite): def test_GET_no_delay(self): """Test a limit handles 1 GET per second.""" - limit = Limit("GET", "*", ".*", 1, 1) + limit = limits.Limit("GET", "*", ".*", 1, 1) delay = limit("GET", "/anything") self.assertEqual(None, delay) self.assertEqual(0, limit.next_request) @@ -238,7 +331,7 @@ class LimitTest(BaseLimitTestSuite): def test_GET_delay(self): """Test two calls to 1 GET per second limit.""" - limit = Limit("GET", "*", ".*", 1, 1) + limit = limits.Limit("GET", "*", ".*", 1, 1) delay = limit("GET", "/anything") self.assertEqual(None, delay) |
