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:
@@ -36,6 +36,19 @@ from neutron.plugins.metaplugin.meta_models_v2 import (NetworkFlavor,
|
|||||||
LOG = logging.getLogger(__name__)
|
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
|
# Metaplugin Exceptions
|
||||||
class FlavorNotFound(exc.NotFound):
|
class FlavorNotFound(exc.NotFound):
|
||||||
message = _("Flavor %(flavor)s could not be found")
|
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:
|
for method_name, flavor in extension_list:
|
||||||
self.extension_map[method_name] = flavor
|
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):
|
def _load_plugin(self, plugin_provider):
|
||||||
LOG.debug(_("Plugin location: %s"), plugin_provider)
|
LOG.debug(_("Plugin location: %s"), plugin_provider)
|
||||||
plugin_klass = importutils.import_class(plugin_provider)
|
plugin_klass = importutils.import_class(plugin_provider)
|
||||||
@@ -190,28 +217,24 @@ class MetaPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
del net['id']
|
del net['id']
|
||||||
return net
|
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):
|
def get_networks(self, context, filters=None, fields=None):
|
||||||
nets = self.get_networks_with_flavor(context, filters, None)
|
nets = []
|
||||||
if filters:
|
for flavor, plugin in self.plugins.items():
|
||||||
nets = self._filter_nets_l3(context, nets, filters)
|
if (filters and FLAVOR_NETWORK in filters and
|
||||||
nets = [self.get_network(context, net['id'], fields)
|
not flavor in filters[FLAVOR_NETWORK]):
|
||||||
for net in nets]
|
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
|
return nets
|
||||||
|
|
||||||
def _get_flavor_by_network_id(self, context, network_id):
|
def _get_flavor_by_network_id(self, context, network_id):
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from neutron.tests.unit.metaplugin.test_metaplugin import setup_metaplugin_conf
|
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_db_plugin as test_plugin
|
||||||
from neutron.tests.unit import test_l3_plugin
|
from neutron.tests.unit import test_l3_plugin
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ class MetaPluginV2DBTestCase(test_plugin.NeutronDbPluginV2TestCase):
|
|||||||
# same signature.
|
# same signature.
|
||||||
setup_metaplugin_conf()
|
setup_metaplugin_conf()
|
||||||
ext_mgr = ext_mgr or test_l3_plugin.L3TestExtensionManager()
|
ext_mgr = ext_mgr or test_l3_plugin.L3TestExtensionManager()
|
||||||
|
self.addCleanup(unregister_meta_hooks)
|
||||||
super(MetaPluginV2DBTestCase, self).setUp(
|
super(MetaPluginV2DBTestCase, self).setUp(
|
||||||
plugin=self._plugin_name, ext_mgr=ext_mgr,
|
plugin=self._plugin_name, ext_mgr=ext_mgr,
|
||||||
service_plugins=service_plugins)
|
service_plugins=service_plugins)
|
||||||
|
@@ -23,6 +23,8 @@ import testtools
|
|||||||
|
|
||||||
from neutron import context
|
from neutron import context
|
||||||
from neutron.db import api as db
|
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.extensions.flavor import (FLAVOR_NETWORK, FLAVOR_ROUTER)
|
||||||
from neutron.openstack.common import uuidutils
|
from neutron.openstack.common import uuidutils
|
||||||
from neutron.plugins.metaplugin.meta_neutron_plugin import FlavorNotFound
|
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')
|
'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 MetaNeutronPluginV2Test(base.BaseTestCase):
|
||||||
"""Class conisting of MetaNeutronPluginV2 unit tests."""
|
"""Class conisting of MetaNeutronPluginV2 unit tests."""
|
||||||
|
|
||||||
@@ -82,6 +91,7 @@ class MetaNeutronPluginV2Test(base.BaseTestCase):
|
|||||||
|
|
||||||
db.configure_db()
|
db.configure_db()
|
||||||
self.addCleanup(db.clear_db)
|
self.addCleanup(db.clear_db)
|
||||||
|
self.addCleanup(unregister_meta_hooks)
|
||||||
|
|
||||||
setup_metaplugin_conf(self.has_l3)
|
setup_metaplugin_conf(self.has_l3)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user