diff --git a/quantum/db/db_base_plugin_v2.py b/quantum/db/db_base_plugin_v2.py index 675ad86eb4..7792a03aaf 100644 --- a/quantum/db/db_base_plugin_v2.py +++ b/quantum/db/db_base_plugin_v2.py @@ -118,7 +118,8 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2): return query @classmethod - def register_model_query_hook(cls, model, name, query_hook, filter_hook): + def register_model_query_hook(cls, model, name, query_hook, filter_hook, + result_filters=None): """ register an hook to be invoked when a query is executed. Add the hooks to the _model_query_hooks dict. Models are the keys @@ -138,7 +139,8 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2): # add key to dict model_hooks = {} cls._model_query_hooks[model] = model_hooks - model_hooks[name] = {'query': query_hook, 'filter': filter_hook} + model_hooks[name] = {'query': query_hook, 'filter': filter_hook, + 'result_filters': result_filters} def _get_by_id(self, context, model, id): query = self._model_query(context, model) @@ -208,6 +210,11 @@ class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2): column = getattr(model, key, None) if column: query = query.filter(column.in_(value)) + for _name, hooks in self._model_query_hooks.get(model, + {}).iteritems(): + result_filter = hooks.get('result_filters', None) + if result_filter: + query = result_filter(self, query, filters) return query def _get_collection_query(self, context, model, filters=None, diff --git a/quantum/db/l3_db.py b/quantum/db/l3_db.py index dd51d11040..d18e59668f 100644 --- a/quantum/db/l3_db.py +++ b/quantum/db/l3_db.py @@ -92,6 +92,14 @@ class L3_NAT_db_mixin(l3.RouterPluginBase): *conditions) return conditions + def _network_result_filter_hook(self, query, filters): + vals = filters and filters.get('router:external', []) + if not vals: + return query + if vals[0]: + return query.filter((ExternalNetwork.network_id != expr.null())) + return query.filter((ExternalNetwork.network_id == expr.null())) + # TODO(salvatore-orlando): Perform this operation without explicitly # referring to db_base_plugin_v2, as plugins that do not extend from it # might exist in the future @@ -99,7 +107,8 @@ class L3_NAT_db_mixin(l3.RouterPluginBase): models_v2.Network, "external_net", _network_model_hook, - _network_filter_hook) + _network_filter_hook, + _network_result_filter_hook) def _get_router(self, context, id): try: diff --git a/quantum/plugins/hyperv/hyperv_quantum_plugin.py b/quantum/plugins/hyperv/hyperv_quantum_plugin.py index 8f2fae99d4..63cce83677 100644 --- a/quantum/plugins/hyperv/hyperv_quantum_plugin.py +++ b/quantum/plugins/hyperv/hyperv_quantum_plugin.py @@ -347,8 +347,6 @@ class HyperVQuantumPlugin(db_base_plugin_v2.QuantumDbPluginV2, self._extend_network_dict_provider(context, net) self._extend_network_dict_l3(context, net) - # TODO(rkukura): Filter on extended provider attributes. - nets = self._filter_nets_l3(context, nets, filters) return [self._fields(net, fields) for net in nets] def _extend_port_dict_binding(self, context, port): diff --git a/quantum/plugins/linuxbridge/lb_quantum_plugin.py b/quantum/plugins/linuxbridge/lb_quantum_plugin.py index 54e4beea22..43ce8de023 100644 --- a/quantum/plugins/linuxbridge/lb_quantum_plugin.py +++ b/quantum/plugins/linuxbridge/lb_quantum_plugin.py @@ -449,9 +449,6 @@ class LinuxBridgePluginV2(db_base_plugin_v2.QuantumDbPluginV2, self._extend_network_dict_provider(context, net) self._extend_network_dict_l3(context, net) - # TODO(rkukura): Filter on extended provider attributes. - nets = self._filter_nets_l3(context, nets, filters) - return [self._fields(net, fields) for net in nets] def _extend_port_dict_binding(self, context, port): diff --git a/quantum/plugins/midonet/plugin.py b/quantum/plugins/midonet/plugin.py index 714364a321..ed92efad7e 100644 --- a/quantum/plugins/midonet/plugin.py +++ b/quantum/plugins/midonet/plugin.py @@ -374,7 +374,6 @@ class MidonetPluginV2(db_base_plugin_v2.QuantumDbPluginV2, id=n['id']) self._extend_network_dict_l3(context, n) - qnets = self._filter_nets_l3(context, qnets, filters) return [self._fields(net, fields) for net in qnets] def delete_network(self, context, id): diff --git a/quantum/plugins/nec/nec_plugin.py b/quantum/plugins/nec/nec_plugin.py index 52a677be71..e6ea05d53a 100644 --- a/quantum/plugins/nec/nec_plugin.py +++ b/quantum/plugins/nec/nec_plugin.py @@ -342,7 +342,6 @@ class NECPluginV2(nec_plugin_base.NECPluginV2Base, nets = super(NECPluginV2, self).get_networks(context, filters, None) for net in nets: self._extend_network_dict_l3(context, net) - nets = self._filter_nets_l3(context, nets, filters) return [self._fields(net, fields) for net in nets] def _extend_port_dict_binding(self, context, port): diff --git a/quantum/plugins/nicira/nicira_nvp_plugin/QuantumPlugin.py b/quantum/plugins/nicira/nicira_nvp_plugin/QuantumPlugin.py index 3ec2ddda8e..1b87c04155 100644 --- a/quantum/plugins/nicira/nicira_nvp_plugin/QuantumPlugin.py +++ b/quantum/plugins/nicira/nicira_nvp_plugin/QuantumPlugin.py @@ -1041,9 +1041,6 @@ class NvpPluginV2(db_base_plugin_v2.QuantumDbPluginV2, self._extend_network_dict_l3(context, net) self._extend_network_qos_queue(context, net) - quantum_lswitches = self._filter_nets_l3(context, - quantum_lswitches, - filters) tenant_ids = filters and filters.get('tenant_id') or None filter_fmt = "&tag=%s&tag_scope=os_tid" if context.is_admin and not tenant_ids: diff --git a/quantum/plugins/openvswitch/ovs_quantum_plugin.py b/quantum/plugins/openvswitch/ovs_quantum_plugin.py index ce22d9edb5..a2382149d5 100644 --- a/quantum/plugins/openvswitch/ovs_quantum_plugin.py +++ b/quantum/plugins/openvswitch/ovs_quantum_plugin.py @@ -538,9 +538,6 @@ class OVSQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2, self._extend_network_dict_provider(context, net) self._extend_network_dict_l3(context, net) - # TODO(rkukura): Filter on extended provider attributes. - nets = self._filter_nets_l3(context, nets, filters) - return [self._fields(net, fields) for net in nets] def _extend_port_dict_binding(self, context, port): diff --git a/quantum/plugins/ryu/ryu_quantum_plugin.py b/quantum/plugins/ryu/ryu_quantum_plugin.py index 58dc0e4e45..f51280caa4 100644 --- a/quantum/plugins/ryu/ryu_quantum_plugin.py +++ b/quantum/plugins/ryu/ryu_quantum_plugin.py @@ -187,7 +187,6 @@ class RyuQuantumPluginV2(db_base_plugin_v2.QuantumDbPluginV2, None) for net in nets: self._extend_network_dict_l3(context, net) - nets = self._filter_nets_l3(context, nets, filters) return [self._fields(net, fields) for net in nets] diff --git a/quantum/tests/unit/test_l3_plugin.py b/quantum/tests/unit/test_l3_plugin.py index 48c97f4cbc..ff86f25d04 100644 --- a/quantum/tests/unit/test_l3_plugin.py +++ b/quantum/tests/unit/test_l3_plugin.py @@ -293,8 +293,6 @@ class TestL3NatPlugin(db_base_plugin_v2.QuantumDbPluginV2, marker=marker, page_reverse=page_reverse) for net in nets: self._extend_network_dict_l3(context, net) - nets = self._filter_nets_l3(context, nets, filters) - return [self._fields(net, fields) for net in nets] def delete_port(self, context, id, l3_port_check=True): @@ -1400,6 +1398,21 @@ class L3NatDBTestCase(L3NatTestCaseBase): query_params="%s=False" % l3.EXTERNAL) self.assertEqual(len(body['networks']), 1) + def test_list_nets_external_pagination(self): + if self._skip_native_pagination: + self.skipTest("Skip test for not implemented pagination feature") + with contextlib.nested(self.network(name='net1'), + self.network(name='net3')) as (n1, n3): + self._set_net_external(n1['network']['id']) + self._set_net_external(n3['network']['id']) + with self.network(name='net2') as n2: + self._test_list_with_pagination( + 'network', (n1, n3), ('name', 'asc'), 1, 3, + query_params='router:external=True') + self._test_list_with_pagination( + 'network', (n2, ), ('name', 'asc'), 1, 2, + query_params='router:external=False') + def test_get_network_succeeds_without_filter(self): plugin = QuantumManager.get_plugin() ctx = context.Context(None, None, is_admin=True)