]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Enhance GET networks performance of metaplugin
authorItsuro Oda <oda@valinux.co.jp>
Tue, 24 Dec 2013 03:27:53 +0000 (12:27 +0900)
committerItsuro Oda <oda@valinux.co.jp>
Wed, 5 Mar 2014 22:30:05 +0000 (07:30 +0900)
Change to call plugin.get_networks() per target plugin
instead of calling plugin.get_network() per network.
Hook routines are used to select networks which belong
the target plugin.

Change-Id: Ieff06ac7bc7a150501f91aecc3197b0bb664d5fa
Closes-Bug: #1267290

neutron/plugins/metaplugin/meta_neutron_plugin.py
neutron/tests/unit/metaplugin/test_basic.py
neutron/tests/unit/metaplugin/test_metaplugin.py

index 4657d467029bb8968ff54ee0d997bc5485a6edf2..837ae5c800d3e2d2834f8fc18f0ffd222d56928b 100644 (file)
@@ -36,6 +36,19 @@ from neutron.plugins.metaplugin.meta_models_v2 import (NetworkFlavor,
 LOG = logging.getLogger(__name__)
 
 
+# Hooks used to select records which belong a target plugin.
+def _meta_network_model_hook(context, original_model, query):
+    return query.outerjoin(NetworkFlavor,
+                           NetworkFlavor.network_id == models_v2.Network.id)
+
+
+def _meta_flavor_filter_hook(query, filters):
+    if FLAVOR_NETWORK in filters:
+        return query.filter(NetworkFlavor.flavor ==
+                            filters[FLAVOR_NETWORK][0])
+    return query
+
+
 # Metaplugin  Exceptions
 class FlavorNotFound(exc.NotFound):
     message = _("Flavor %(flavor)s could not be found")
@@ -111,6 +124,20 @@ class MetaPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
             for method_name, flavor in extension_list:
                 self.extension_map[method_name] = flavor
 
+        # Register hooks.
+        # The hooks are applied for each target plugin instance when
+        # calling the base class to get networks so that only records
+        # which belong to the plugin are selected.
+        #NOTE: Doing registration here (within __init__()) is to avoid
+        # registration when merely importing this file. This is only
+        # for running whole unit tests.
+        db_base_plugin_v2.NeutronDbPluginV2.register_model_query_hook(
+            models_v2.Network,
+            'metaplugin_net',
+            _meta_network_model_hook,
+            None,
+            _meta_flavor_filter_hook)
+
     def _load_plugin(self, plugin_provider):
         LOG.debug(_("Plugin location: %s"), plugin_provider)
         plugin_klass = importutils.import_class(plugin_provider)
@@ -190,28 +217,24 @@ class MetaPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
             del net['id']
         return net
 
-    def get_networks_with_flavor(self, context, filters=None,
-                                 fields=None):
-        collection = self._model_query(context, models_v2.Network)
-        model = NetworkFlavor
-        collection = collection.join(model,
-                                     models_v2.Network.id == model.network_id)
-        if filters:
-            for key, value in filters.iteritems():
-                if key == FLAVOR_NETWORK:
-                    column = NetworkFlavor.flavor
-                else:
-                    column = getattr(models_v2.Network, key, None)
-                if column:
-                    collection = collection.filter(column.in_(value))
-        return [self._make_network_dict(c, fields) for c in collection]
-
     def get_networks(self, context, filters=None, fields=None):
-        nets = self.get_networks_with_flavor(context, filters, None)
-        if filters:
-            nets = self._filter_nets_l3(context, nets, filters)
-        nets = [self.get_network(context, net['id'], fields)
-                for net in nets]
+        nets = []
+        for flavor, plugin in self.plugins.items():
+            if (filters and FLAVOR_NETWORK in filters and
+                    not flavor in filters[FLAVOR_NETWORK]):
+                continue
+            if filters:
+                #NOTE: copy each time since a target plugin may modify
+                # plugin_filters.
+                plugin_filters = filters.copy()
+            else:
+                plugin_filters = {}
+            plugin_filters[FLAVOR_NETWORK] = [flavor]
+            plugin_nets = plugin.get_networks(context, plugin_filters, fields)
+            for net in plugin_nets:
+                if not fields or FLAVOR_NETWORK in fields:
+                    net[FLAVOR_NETWORK] = flavor
+                nets.append(net)
         return nets
 
     def _get_flavor_by_network_id(self, context, network_id):
index 876b824d0083c430a49db91499605d9cdbf70803..de407fd809cea6bb0945206123c62e16f124eed4 100644 (file)
@@ -14,6 +14,7 @@
 # limitations under the License.
 
 from neutron.tests.unit.metaplugin.test_metaplugin import setup_metaplugin_conf
+from neutron.tests.unit.metaplugin.test_metaplugin import unregister_meta_hooks
 from neutron.tests.unit import test_db_plugin as test_plugin
 from neutron.tests.unit import test_l3_plugin
 
@@ -31,6 +32,7 @@ class MetaPluginV2DBTestCase(test_plugin.NeutronDbPluginV2TestCase):
         # same signature.
         setup_metaplugin_conf()
         ext_mgr = ext_mgr or test_l3_plugin.L3TestExtensionManager()
+        self.addCleanup(unregister_meta_hooks)
         super(MetaPluginV2DBTestCase, self).setUp(
             plugin=self._plugin_name, ext_mgr=ext_mgr,
             service_plugins=service_plugins)
index 6e70703d346a78135489bbd87d7e889b50a9310d..d02ac13a61caf5121c28565cb474611dd2627df3 100644 (file)
@@ -23,6 +23,8 @@ import testtools
 
 from neutron import context
 from neutron.db import api as db
+from neutron.db import db_base_plugin_v2
+from neutron.db import models_v2
 from neutron.extensions.flavor import (FLAVOR_NETWORK, FLAVOR_ROUTER)
 from neutron.openstack.common import uuidutils
 from neutron.plugins.metaplugin.meta_neutron_plugin import FlavorNotFound
@@ -68,6 +70,13 @@ def setup_metaplugin_conf(has_l3=True):
                           'neutron.openstack.common.rpc.impl_fake')
 
 
+# Hooks registered by metaplugin must not exist for other plugins UT.
+# So hooks must be unregistered (overwrite to None in fact).
+def unregister_meta_hooks():
+    db_base_plugin_v2.NeutronDbPluginV2.register_model_query_hook(
+        models_v2.Network, 'metaplugin_net', None, None, None)
+
+
 class MetaNeutronPluginV2Test(base.BaseTestCase):
     """Class conisting of MetaNeutronPluginV2 unit tests."""
 
@@ -82,6 +91,7 @@ class MetaNeutronPluginV2Test(base.BaseTestCase):
 
         db.configure_db()
         self.addCleanup(db.clear_db)
+        self.addCleanup(unregister_meta_hooks)
 
         setup_metaplugin_conf(self.has_l3)