shim model query hooks to use neutron-lib
This patch shims the model query hook functionality to use neutron-lib. A shim is used as the query hooks are cached in a shared dict and by shimming them to use neutron-lib we can let consumers move over to neutron-lib's version at will. Once all current consumers are moved over to lib, we can remove the shim and consume from lib directly. The DBQueryHooksFixture is also used in this patch to replace the existing cleanup function in the unit tests. Change-Id: I18a4e836ce89b607b5452527e5f8dd172cad6b4f
This commit is contained in:
parent
858a7ff42d
commit
5c208a313a
|
@ -17,6 +17,7 @@ NOTE: This module shall not be used by external projects. It will be moved
|
|||
"""
|
||||
|
||||
from neutron_lib.api import attributes
|
||||
from neutron_lib.db import model_query
|
||||
from neutron_lib.db import utils as db_utils
|
||||
from neutron_lib.objects import utils as obj_utils
|
||||
from neutron_lib.utils import helpers
|
||||
|
@ -25,111 +26,10 @@ from sqlalchemy import sql, or_, and_
|
|||
from sqlalchemy.ext import associationproxy
|
||||
|
||||
|
||||
# Classes implementing extensions will register hooks into this dictionary
|
||||
# for "augmenting" the "core way" of building a query for retrieving objects
|
||||
# from a model class. Hooks are registered by invoking register_hook().
|
||||
_model_query_hooks = {
|
||||
# model1 : {
|
||||
# hook1: {
|
||||
# 'query': query_hook,
|
||||
# 'filter': filter_hook,
|
||||
# 'result_filters': result_filters
|
||||
# },
|
||||
# hook2: {
|
||||
# 'query': query_hook,
|
||||
# 'filter': filter_hook,
|
||||
# 'result_filters': result_filters
|
||||
# },
|
||||
# ...
|
||||
# },
|
||||
# model2 : {
|
||||
# hook1: {
|
||||
# 'query': query_hook,
|
||||
# 'filter': filter_hook,
|
||||
# 'result_filters': result_filters
|
||||
# },
|
||||
# hook2: {
|
||||
# 'query': query_hook,
|
||||
# 'filter': filter_hook,
|
||||
# 'result_filters': result_filters
|
||||
# },
|
||||
# ...
|
||||
# },
|
||||
# ...
|
||||
}
|
||||
|
||||
|
||||
def register_hook(model, name, query_hook, filter_hook,
|
||||
result_filters=None):
|
||||
"""Register a hook to be invoked when a query is executed.
|
||||
|
||||
:param model: The DB Model that the hook applies to.
|
||||
:type model: sqlalchemy orm model
|
||||
|
||||
:param name: A name for the hook.
|
||||
:type name: str
|
||||
|
||||
:param query_hook: The method to be called to augment the query.
|
||||
:type query_hook: callable or None
|
||||
|
||||
:param filter_hook: A method to be called to augment the query filter.
|
||||
:type filter_hook: callable or None
|
||||
|
||||
:param result_filters: A Method to be called to filter the query result.
|
||||
:type result_filters: callable or None
|
||||
|
||||
Adds the hook components to the _model_query_hooks dict. Models are the
|
||||
keys of this dict, whereas the value is another dict mapping hook names
|
||||
to callables performing the hook.
|
||||
|
||||
Each hook has three components:
|
||||
"query", used to build the query expression
|
||||
"filter", used to build the filter expression
|
||||
"result_filters", used for final filtering on the query result
|
||||
|
||||
Query hooks take as input the query being built and return a
|
||||
transformed query expression.
|
||||
def mymodel_query_hook(context, original_model, query):
|
||||
augmented_query = ...
|
||||
return augmented_query
|
||||
|
||||
Filter hooks take as input the filter expression being built and return
|
||||
a transformed filter expression
|
||||
def mymodel_filter_hook(context, original_model, filters):
|
||||
refined_filters = ...
|
||||
return refined_filters
|
||||
|
||||
Result filter hooks take as input the query expression and the filter
|
||||
expression, and return a final transformed query expression.
|
||||
def mymodel_result_filter_hook(query, filters):
|
||||
final_filters = ...
|
||||
return query.filter(final_filters)
|
||||
|
||||
"""
|
||||
if callable(query_hook):
|
||||
query_hook = helpers.make_weak_ref(query_hook)
|
||||
if callable(filter_hook):
|
||||
filter_hook = helpers.make_weak_ref(filter_hook)
|
||||
if callable(result_filters):
|
||||
result_filters = helpers.make_weak_ref(result_filters)
|
||||
_model_query_hooks.setdefault(model, {})[name] = {
|
||||
'query': query_hook,
|
||||
'filter': filter_hook,
|
||||
'result_filters': result_filters
|
||||
}
|
||||
|
||||
|
||||
def get_hooks(model):
|
||||
"""Retrieve the model query hooks for a model.
|
||||
|
||||
:param model: The DB Model to look up for query hooks.
|
||||
:type model: sqlalchemy orm model
|
||||
|
||||
:return: list of hooks
|
||||
:rtype: list of dict of callable
|
||||
|
||||
"""
|
||||
return _model_query_hooks.get(model, {}).values()
|
||||
# TODO(boden): remove shims
|
||||
_model_query_hooks = model_query._model_query_hooks
|
||||
register_hook = model_query.register_hook
|
||||
get_hooks = model_query.get_hooks
|
||||
|
||||
|
||||
def query_with_hooks(context, model):
|
||||
|
|
|
@ -47,7 +47,6 @@ from neutron.api.rpc.callbacks.producer import registry as rpc_producer_reg
|
|||
from neutron.common import config
|
||||
from neutron.common import rpc as n_rpc
|
||||
from neutron.conf.agent import common as agent_config
|
||||
from neutron.db import _model_query as model_query
|
||||
from neutron.db import _resource_extend as resource_extend
|
||||
from neutron.db import agentschedulers_db
|
||||
from neutron import manager
|
||||
|
@ -184,6 +183,8 @@ class DietTestCase(base.BaseTestCase):
|
|||
# Make sure we see all relevant deprecation warnings when running tests
|
||||
self.useFixture(tools.WarningsFixture())
|
||||
|
||||
self.useFixture(fixture.DBQueryHooksFixture())
|
||||
|
||||
# NOTE(ihrachys): oslotest already sets stopall for cleanup, but it
|
||||
# does it using six.moves.mock (the library was moved into
|
||||
# unittest.mock in Python 3.4). So until we switch to six.moves.mock
|
||||
|
@ -192,7 +193,6 @@ class DietTestCase(base.BaseTestCase):
|
|||
# six before removing the cleanup callback from here.
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
|
||||
self.addCleanup(self.reset_model_query_hooks)
|
||||
self.addCleanup(self.reset_resource_extend_functions)
|
||||
|
||||
self.addOnException(self.check_for_systemexit)
|
||||
|
@ -200,10 +200,6 @@ class DietTestCase(base.BaseTestCase):
|
|||
|
||||
tools.reset_random_seed()
|
||||
|
||||
@staticmethod
|
||||
def reset_model_query_hooks():
|
||||
model_query._model_query_hooks = {}
|
||||
|
||||
@staticmethod
|
||||
def reset_resource_extend_functions():
|
||||
resource_extend._resource_extend_functions = {}
|
||||
|
|
Loading…
Reference in New Issue