]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
rpc.callbacks.registry: validate type of callback result
authorIhar Hrachyshka <ihrachys@redhat.com>
Sat, 25 Jul 2015 19:35:44 +0000 (21:35 +0200)
committerIhar Hrachyshka <ihrachys@redhat.com>
Mon, 27 Jul 2015 12:04:34 +0000 (14:04 +0200)
Enforce appropriate type for the object returned by rpc callback.

Partially-Implements: blueprint quantum-qos-api
Change-Id: I994253ac15320254104862d2df8dacfc7fc00014

neutron/api/rpc/callbacks/registry.py
neutron/tests/unit/api/rpc/callbacks/test_registry.py [new file with mode: 0644]
neutron/tests/unit/api/rpc/callbacks/test_resource_manager.py

index 931cce20be6c188e0f8e5109505b491ef672fdfa..1fb77c41b374214ac2bc747da4a2cad6ac43298a 100644 (file)
@@ -11,6 +11,9 @@
 #    under the License.
 
 from neutron.api.rpc.callbacks import resource_manager
+from neutron.api.rpc.callbacks import resources
+from neutron.common import exceptions
+
 
 # TODO(ajo): consider adding locking
 CALLBACK_MANAGER = None
@@ -23,6 +26,10 @@ def _get_resources_callback_manager():
     return CALLBACK_MANAGER
 
 
+class CallbackReturnedWrongObjectType(exceptions.NeutronException):
+    message = _('Callback for %(resource_type)s returned wrong object type')
+
+
 #resource implementation callback registration functions
 def get_info(resource_type, resource_id, **kwargs):
     """Get information about resource type with resource id.
@@ -34,7 +41,13 @@ def get_info(resource_type, resource_id, **kwargs):
     """
     callback = _get_resources_callback_manager().get_callback(resource_type)
     if callback:
-        return callback(resource_type, resource_id, **kwargs)
+        obj = callback(resource_type, resource_id, **kwargs)
+        if obj:
+            expected_cls = resources.get_resource_cls(resource_type)
+            if not isinstance(obj, expected_cls):
+                raise CallbackReturnedWrongObjectType(
+                    resource_type=resource_type)
+        return obj
 
 
 def register_provider(callback, resource_type):
diff --git a/neutron/tests/unit/api/rpc/callbacks/test_registry.py b/neutron/tests/unit/api/rpc/callbacks/test_registry.py
new file mode 100644 (file)
index 0000000..dbe27b2
--- /dev/null
@@ -0,0 +1,58 @@
+#    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 mock
+
+from neutron.api.rpc.callbacks import registry
+from neutron.api.rpc.callbacks import resource_manager
+from neutron.api.rpc.callbacks import resources
+from neutron.objects.qos import policy
+from neutron.tests import base
+
+
+class GetInfoTestCase(base.BaseTestCase):
+    def setUp(self):
+        super(GetInfoTestCase, self).setUp()
+        mgr = resource_manager.ResourcesCallbacksManager()
+        mgr_p = mock.patch.object(
+            registry, '_get_resources_callback_manager', return_value=mgr)
+        mgr_p.start()
+
+    def test_returns_callback_result(self):
+        policy_obj = policy.QosPolicy(context=None)
+
+        def _fake_policy_cb(*args, **kwargs):
+            return policy_obj
+
+        registry.register_provider(_fake_policy_cb, resources.QOS_POLICY)
+
+        self.assertEqual(policy_obj,
+                         registry.get_info(resources.QOS_POLICY, 'fake_id'))
+
+    def test_does_not_raise_on_none(self):
+        def _wrong_type_cb(*args, **kwargs):
+            pass
+
+        registry.register_provider(_wrong_type_cb, resources.QOS_POLICY)
+
+        obj = registry.get_info(resources.QOS_POLICY, 'fake_id')
+        self.assertIsNone(obj)
+
+    def test_raises_on_wrong_object_type(self):
+        def _wrong_type_cb(*args, **kwargs):
+            return object()
+
+        registry.register_provider(_wrong_type_cb, resources.QOS_POLICY)
+
+        self.assertRaises(
+            registry.CallbackReturnedWrongObjectType,
+            registry.get_info, resources.QOS_POLICY, 'fake_id')
index 7e9f58898453706fabc8f3027c483178ae113320..bc708dbbd28d488ea1079a8c10f3e6e190b599fd 100644 (file)
@@ -13,6 +13,8 @@
 
 from neutron.api.rpc.callbacks import registry as rpc_registry
 from neutron.api.rpc.callbacks import resources
+from neutron.objects.qos import policy
+from neutron.objects.qos import rule
 
 
 from neutron.tests import base
@@ -27,21 +29,22 @@ class ResourcesCallbackRequestTestCase(base.BaseTestCase):
 
     def test_resource_callback_request(self):
 
-        #TODO(QoS) convert it to the version object format
         def _get_qos_policy_cb(resource, policy_id, **kwargs):
-            qos_policy = {
-                "tenant_id": "8d4c70a21fed4aeba121a1a429ba0d04",
-                "id": "46ebaec0-0570-43ac-82f6-60d2b03168c4",
-                "name": "10Mbit",
-                "description": "This policy limits the ports to 10Mbit max.",
-                "shared": False,
-                "rules": [{
-                    "id": "5f126d84-551a-4dcf-bb01-0e9c0df0c793",
-                    "max_kbps": "10000",
-                    "max_burst_kbps": "0",
-                    "type": "bnadwidth_limit"
-                }]
-            }
+            context = kwargs.get('context')
+            qos_policy = policy.QosPolicy(context,
+                tenant_id="8d4c70a21fed4aeba121a1a429ba0d04",
+                id="46ebaec0-0570-43ac-82f6-60d2b03168c4",
+                name="10Mbit",
+                description="This policy limits the ports to 10Mbit max.",
+                shared=False,
+                rules=[
+                    rule.QosBandwidthLimitRule(context,
+                        id="5f126d84-551a-4dcf-bb01-0e9c0df0c793",
+                        max_kbps=10000,
+                        max_burst_kbps=0)
+                ]
+            )
+            qos_policy.obj_reset_changes()
             return qos_policy
 
         rpc_registry.register_provider(