use sqla functions from neutron-lib

The public db apis are available in neutron-lib. This patch consumes
the sqla_listen, sqla_remove and sqla_remove_all functions from lib
by removing them from neutron and using lib's version.

There's also a TODO added here so we can eventually rehome the
check_no_sqlalchemy_event_import hacking check to neutron-lib.

NeutronLibImpact

Change-Id: I3b3862016125303fb227b4ff41420a89bb33c917
This commit is contained in:
Boden R 2018-07-18 08:33:38 -06:00 committed by Slawek Kaplonski
parent 6c97347cac
commit c774930aed
11 changed files with 29 additions and 54 deletions

View File

@ -31,7 +31,6 @@ from pecan import util as p_util
import six import six
import sqlalchemy import sqlalchemy
from sqlalchemy import event # noqa from sqlalchemy import event # noqa
from sqlalchemy import exc as sql_exc
from sqlalchemy import orm from sqlalchemy import orm
from sqlalchemy.orm import exc from sqlalchemy.orm import exc
@ -148,35 +147,6 @@ def autonested_transaction(sess):
yield tx yield tx
_REGISTERED_SQLA_EVENTS = []
def sqla_listen(*args):
"""Wrapper to track subscribers for test teardowns.
SQLAlchemy has no "unsubscribe all" option for its event listener
framework so we need to keep track of the subscribers by having
them call through here for test teardowns.
"""
event.listen(*args)
_REGISTERED_SQLA_EVENTS.append(args)
def sqla_remove(*args):
event.remove(*args)
_REGISTERED_SQLA_EVENTS.remove(args)
def sqla_remove_all():
for args in _REGISTERED_SQLA_EVENTS:
try:
event.remove(*args)
except sql_exc.InvalidRequestError:
# already removed
pass
del _REGISTERED_SQLA_EVENTS[:]
@event.listens_for(orm.session.Session, "after_flush") @event.listens_for(orm.session.Session, "after_flush")
def add_to_rel_load_list(session, flush_context=None): def add_to_rel_load_list(session, flush_context=None):
# keep track of new items to load relationships on during commit # keep track of new items to load relationships on during commit

View File

@ -162,12 +162,13 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
# NOTE(arosen) These event listeners are here to hook into when # NOTE(arosen) These event listeners are here to hook into when
# port status changes and notify nova about their change. # port status changes and notify nova about their change.
self.nova_notifier = nova.Notifier.get_instance() self.nova_notifier = nova.Notifier.get_instance()
db_api.sqla_listen(models_v2.Port, 'after_insert', lib_db_api.sqla_listen(models_v2.Port, 'after_insert',
self.nova_notifier.send_port_status) self.nova_notifier.send_port_status)
db_api.sqla_listen(models_v2.Port, 'after_update', lib_db_api.sqla_listen(models_v2.Port, 'after_update',
self.nova_notifier.send_port_status) self.nova_notifier.send_port_status)
db_api.sqla_listen(models_v2.Port.status, 'set', lib_db_api.sqla_listen(
self.nova_notifier.record_port_status_changed) models_v2.Port.status, 'set',
self.nova_notifier.record_port_status_changed)
@registry.receives(resources.RBAC_POLICY, [events.BEFORE_CREATE, @registry.receives(resources.RBAC_POLICY, [events.BEFORE_CREATE,
events.BEFORE_UPDATE, events.BEFORE_UPDATE,

View File

@ -243,6 +243,7 @@ def check_python3_no_filter(logical_line):
yield(0, msg) yield(0, msg)
# TODO(boden): rehome this check to neutron-lib
@flake8ext @flake8ext
def check_no_sqlalchemy_event_import(logical_line, filename, noqa): def check_no_sqlalchemy_event_import(logical_line, filename, noqa):
"""N346 - Use neutron.db.api.sqla_listen instead of sqlalchemy event.""" """N346 - Use neutron.db.api.sqla_listen instead of sqlalchemy event."""
@ -256,8 +257,8 @@ def check_no_sqlalchemy_event_import(logical_line, filename, noqa):
if kw not in logical_line: if kw not in logical_line:
return return
yield (0, "N346: Register sqlalchemy events through " yield (0, "N346: Register sqlalchemy events through "
"neutron.db.api.sqla_listen so they can be cleaned up between " "neutron_lib.db.api.sqla_listen so they can be cleaned up "
"unit tests") "between unit tests")
def factory(register): def factory(register):

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from neutron_lib.db import api as lib_db_api
from neutron_lib.plugins import constants from neutron_lib.plugins import constants
from neutron_lib.plugins import directory from neutron_lib.plugins import directory
from oslo_config import cfg from oslo_config import cfg
@ -318,19 +319,19 @@ class TrackedResource(BaseResource):
self._model_class) self._model_class)
def register_events(self): def register_events(self):
listen = db_api.sqla_listen listen = lib_db_api.sqla_listen
listen(self._model_class, 'after_insert', self._db_event_handler) listen(self._model_class, 'after_insert', self._db_event_handler)
listen(self._model_class, 'after_delete', self._db_event_handler) listen(self._model_class, 'after_delete', self._db_event_handler)
listen(se.Session, 'after_bulk_delete', self._except_bulk_delete) listen(se.Session, 'after_bulk_delete', self._except_bulk_delete)
def unregister_events(self): def unregister_events(self):
try: try:
db_api.sqla_remove(self._model_class, 'after_insert', lib_db_api.sqla_remove(self._model_class, 'after_insert',
self._db_event_handler) self._db_event_handler)
db_api.sqla_remove(self._model_class, 'after_delete', lib_db_api.sqla_remove(self._model_class, 'after_delete',
self._db_event_handler) self._db_event_handler)
db_api.sqla_remove(se.Session, 'after_bulk_delete', lib_db_api.sqla_remove(se.Session, 'after_bulk_delete',
self._except_bulk_delete) self._except_bulk_delete)
except sql_exc.InvalidRequestError: except sql_exc.InvalidRequestError:
LOG.warning("No sqlalchemy event for resource %s found", LOG.warning("No sqlalchemy event for resource %s found",
self.name) self.name)

View File

@ -14,8 +14,7 @@
import random import random
import time import time
from neutron.db import api as db_api from neutron_lib.db import api as db_api
from neutron_lib.services import base as service_base from neutron_lib.services import base as service_base
from oslo_db import exception as db_exc from oslo_db import exception as db_exc
from oslo_log import log as logging from oslo_log import log as logging

View File

@ -11,6 +11,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from neutron_lib.db import api as db_api
from neutron_lib.services import base as service_base from neutron_lib.services import base as service_base
from oslo_log import log as logging from oslo_log import log as logging
import sqlalchemy import sqlalchemy
@ -20,7 +21,6 @@ import webob.exc
from neutron._i18n import _ from neutron._i18n import _
from neutron.db import _resource_extend as resource_extend from neutron.db import _resource_extend as resource_extend
from neutron.db import api as db_api
from neutron.db import standard_attr from neutron.db import standard_attr
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)

View File

@ -12,13 +12,13 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from neutron_lib.db import api as db_api
from neutron_lib import exceptions as n_exc from neutron_lib import exceptions as n_exc
from oslo_utils import timeutils from oslo_utils import timeutils
from sqlalchemy.orm import session as se from sqlalchemy.orm import session as se
from neutron.db import _model_query as model_query from neutron.db import _model_query as model_query
from neutron.db import _resource_extend as resource_extend from neutron.db import _resource_extend as resource_extend
from neutron.db import api as db_api
from neutron.db import standard_attr from neutron.db import standard_attr
CHANGED_SINCE = 'changed_since' CHANGED_SINCE = 'changed_since'

View File

@ -27,6 +27,7 @@ import eventlet.timeout
import fixtures import fixtures
import mock import mock
from neutron_lib.callbacks import manager as registry_manager from neutron_lib.callbacks import manager as registry_manager
from neutron_lib.db import api as db_api
from neutron_lib import fixture from neutron_lib import fixture
from oslo_concurrency.fixture import lockutils from oslo_concurrency.fixture import lockutils
from oslo_config import cfg from oslo_config import cfg
@ -49,7 +50,6 @@ from neutron.conf.agent import common as agent_config
from neutron.db import _model_query as model_query from neutron.db import _model_query as model_query
from neutron.db import _resource_extend as resource_extend from neutron.db import _resource_extend as resource_extend
from neutron.db import agentschedulers_db from neutron.db import agentschedulers_db
from neutron.db import api as db_api
from neutron import manager from neutron import manager
from neutron import policy from neutron import policy
from neutron.quota import resource_registry from neutron.quota import resource_registry

View File

@ -25,6 +25,7 @@ from neutron_lib.callbacks import exceptions
from neutron_lib.callbacks import registry from neutron_lib.callbacks import registry
from neutron_lib import constants from neutron_lib import constants
from neutron_lib import context from neutron_lib import context
from neutron_lib.db import api as lib_db_api
from neutron_lib import exceptions as lib_exc from neutron_lib import exceptions as lib_exc
from neutron_lib import fixture from neutron_lib import fixture
from neutron_lib.plugins import directory from neutron_lib.plugins import directory
@ -6699,7 +6700,7 @@ class DbOperationBoundMixin(object):
self._recorded_statements.append(str(clauseelement)) self._recorded_statements.append(str(clauseelement))
engine = db_api.context_manager.writer.get_engine() engine = db_api.context_manager.writer.get_engine()
db_api.sqla_listen(engine, 'after_execute', _event_incrementer) lib_db_api.sqla_listen(engine, 'after_execute', _event_incrementer)
def _get_context(self): def _get_context(self):
if self.admin: if self.admin:

View File

@ -29,6 +29,7 @@ from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources from neutron_lib.callbacks import resources
from neutron_lib import constants from neutron_lib import constants
from neutron_lib import context from neutron_lib import context
from neutron_lib.db import api as lib_db_api
from neutron_lib import exceptions as exc from neutron_lib import exceptions as exc
from neutron_lib import fixture from neutron_lib import fixture
from neutron_lib.plugins import constants as plugin_constants from neutron_lib.plugins import constants as plugin_constants
@ -1282,8 +1283,9 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase):
listener = IPAllocationsGrenade() listener = IPAllocationsGrenade()
engine = db_api.context_manager.writer.get_engine() engine = db_api.context_manager.writer.get_engine()
db_api.sqla_listen(engine, 'before_cursor_execute', listener.execute) lib_db_api.sqla_listen(engine, 'before_cursor_execute',
db_api.sqla_listen(engine, 'commit', listener.commit) listener.execute)
lib_db_api.sqla_listen(engine, 'commit', listener.commit)
func() func()
# make sure that the grenade went off during the commit # make sure that the grenade went off during the commit
self.assertTrue(listener.except_raised) self.assertTrue(listener.except_raised)

View File

@ -15,6 +15,7 @@
import netaddr import netaddr
from neutron_lib import context as nctx from neutron_lib import context as nctx
from neutron_lib.db import api as db_api
from neutron_lib.plugins import constants from neutron_lib.plugins import constants
from neutron_lib.plugins import directory from neutron_lib.plugins import directory
from oslo_config import cfg from oslo_config import cfg
@ -23,7 +24,6 @@ from oslo_utils import uuidutils
from sqlalchemy.orm import session as se from sqlalchemy.orm import session as se
from webob import exc from webob import exc
from neutron.db import api as db_api
from neutron.db import models_v2 from neutron.db import models_v2
from neutron.objects import ports as port_obj from neutron.objects import ports as port_obj
from neutron.tests.unit.plugins.ml2 import test_plugin from neutron.tests.unit.plugins.ml2 import test_plugin