]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Simplify extension processing
authorYAMAMOTO Takashi <yamamoto@midokura.com>
Tue, 29 Sep 2015 10:58:53 +0000 (19:58 +0900)
committerYAMAMOTO Takashi <yamamoto@midokura.com>
Wed, 30 Sep 2015 06:29:06 +0000 (15:29 +0900)
Now ExtensionDescriptor defines the contract for extensions,
don't bother to check existence of attributes which exists in
ExtensionDescriptor.

Also, reject extensions not derived from ExtensionDescriptor.

Closes-Bug: #1501186
Change-Id: I48e179b8739b61f336f5180a22fc66283b9b6991

neutron/api/extensions.py
neutron/tests/unit/extension_stubs.py
neutron/tests/unit/extensions/foxinsocks.py
neutron/tests/unit/extensions/v2attributes.py

index 4af58774ac9d50dd981b5dc70e895c262d589a36..c78b5a07d18fa4a52c4e380eb12271bfc6897e9b 100644 (file)
@@ -144,6 +144,10 @@ class ExtensionDescriptor(object):
         """
         return None
 
+    def get_required_extensions(self):
+        """Returns a list of extensions to be processed before this one."""
+        return []
+
     def update_attributes_map(self, extended_attributes,
                               extension_attrs_map=None):
         """Update attributes map for this extension.
@@ -389,36 +393,21 @@ class ExtensionManager(object):
         resources.append(ResourceExtension('extensions',
                                            ExtensionController(self)))
         for ext in self.extensions.values():
-            try:
-                resources.extend(ext.get_resources())
-            except AttributeError:
-                # NOTE(dprince): Extension aren't required to have resource
-                # extensions
-                pass
+            resources.extend(ext.get_resources())
         return resources
 
     def get_actions(self):
         """Returns a list of ActionExtension objects."""
         actions = []
         for ext in self.extensions.values():
-            try:
-                actions.extend(ext.get_actions())
-            except AttributeError:
-                # NOTE(dprince): Extension aren't required to have action
-                # extensions
-                pass
+            actions.extend(ext.get_actions())
         return actions
 
     def get_request_extensions(self):
         """Returns a list of RequestExtension objects."""
         request_exts = []
         for ext in self.extensions.values():
-            try:
-                request_exts.extend(ext.get_request_extensions())
-            except AttributeError:
-                # NOTE(dprince): Extension aren't required to have request
-                # extensions
-                pass
+            request_exts.extend(ext.get_request_extensions())
         return request_exts
 
     def extend_resources(self, version, attr_map):
@@ -430,33 +419,22 @@ class ExtensionManager(object):
         After this function, we will extend the attr_map if an extension
         wants to extend this map.
         """
-        update_exts = []
-        processed_exts = set()
+        processed_exts = {}
         exts_to_process = self.extensions.copy()
         # Iterate until there are unprocessed extensions or if no progress
         # is made in a whole iteration
         while exts_to_process:
             processed_ext_count = len(processed_exts)
             for ext_name, ext in list(exts_to_process.items()):
-                if not hasattr(ext, 'get_extended_resources'):
-                    del exts_to_process[ext_name]
+                # Process extension only if all required extensions
+                # have been processed already
+                required_exts_set = set(ext.get_required_extensions())
+                if required_exts_set - set(processed_exts):
                     continue
-                if hasattr(ext, 'update_attributes_map'):
-                    update_exts.append(ext)
-                if hasattr(ext, 'get_required_extensions'):
-                    # Process extension only if all required extensions
-                    # have been processed already
-                    required_exts_set = set(ext.get_required_extensions())
-                    if required_exts_set - processed_exts:
-                        continue
-                try:
-                    extended_attrs = ext.get_extended_resources(version)
-                    for res, resource_attrs in six.iteritems(extended_attrs):
-                        attr_map.setdefault(res, {}).update(resource_attrs)
-                except AttributeError:
-                    LOG.exception(_LE("Error fetching extended attributes for "
-                                      "extension '%s'"), ext.get_name())
-                processed_exts.add(ext_name)
+                extended_attrs = ext.get_extended_resources(version)
+                for res, resource_attrs in six.iteritems(extended_attrs):
+                    attr_map.setdefault(res, {}).update(resource_attrs)
+                processed_exts[ext_name] = ext
                 del exts_to_process[ext_name]
             if len(processed_exts) == processed_ext_count:
                 # Exit loop as no progress was made
@@ -468,7 +446,7 @@ class ExtensionManager(object):
                       ','.join(exts_to_process.keys()))
 
         # Extending extensions' attributes map.
-        for ext in update_exts:
+        for ext in processed_exts.values():
             ext.update_attributes_map(attr_map)
 
     def _check_extension(self, extension):
@@ -482,7 +460,7 @@ class ExtensionManager(object):
             LOG.exception(_LE("Exception loading extension: %s"),
                           six.text_type(ex))
             return False
-        return True
+        return isinstance(extension, ExtensionDescriptor)
 
     def _load_all_extensions(self):
         """Load extensions from the configured path.
@@ -567,8 +545,7 @@ class PluginAwareExtensionManager(ExtensionManager):
         return supports_extension
 
     def _plugins_implement_interface(self, extension):
-        if(not hasattr(extension, "get_plugin_interface") or
-           extension.get_plugin_interface() is None):
+        if extension.get_plugin_interface() is None:
             return True
         for plugin in self.plugins.values():
             if isinstance(plugin, extension.get_plugin_interface()):
index f98d2149186fda91f9016e944f55c6baa545975a..bd3bbdc6bf84f07df57a4d689b6aa8c447b02ee8 100644 (file)
@@ -19,7 +19,7 @@ from neutron.api import extensions
 from neutron import wsgi
 
 
-class StubExtension(object):
+class StubExtension(extensions.ExtensionDescriptor):
 
     def __init__(self, alias="stub_extension"):
         self.alias = alias
index 88908a4902c7a9017323c5ea4ec062698d59810c..d42f2b4942c2a0160d9425a81ce99e392da59d3a 100644 (file)
@@ -34,7 +34,7 @@ class FoxInSocksPluginInterface(extensions.PluginInterface):
         pass
 
 
-class Foxinsocks(object):
+class Foxinsocks(extensions.ExtensionDescriptor):
 
     def __init__(self):
         pass
index 6259eb3565948830b90389ae454587f0e59d5ae6..2adfcc12fa69974565a2a3bf351da8a2d313339e 100644 (file)
@@ -13,6 +13,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from neutron.api import extensions
+
+
 EXTENDED_ATTRIBUTES_2_0 = {
     'networks': {
         'v2attrs:something': {'allow_post': False,
@@ -25,7 +28,7 @@ EXTENDED_ATTRIBUTES_2_0 = {
 }
 
 
-class V2attributes(object):
+class V2attributes(extensions.ExtensionDescriptor):
     def get_name(self):
         return "V2 Extended Attributes Example"