Enhance GET networks performance of metaplugin

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
This commit is contained in:
Itsuro Oda 2013-12-24 12:27:53 +09:00
parent 92b5fe2e09
commit f86d5fab74
3 changed files with 56 additions and 21 deletions

View 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):

View 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)

View 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)