diff --git a/neutron/common/utils.py b/neutron/common/utils.py index c1e114888ce..269b9f7f0cf 100644 --- a/neutron/common/utils.py +++ b/neutron/common/utils.py @@ -695,7 +695,7 @@ def transaction_guard(f): n_context.ContextBaseWithSession) else args[1]) # FIXME(kevinbenton): get rid of all uses of this flag - if (is_session_active(context.session) and + if (db_api.is_session_active(context.session) and getattr(context, 'GUARD_TRANSACTION', True)): raise RuntimeError(_("Method %s cannot be called within a " "transaction.") % f) @@ -1029,27 +1029,6 @@ def skip_exceptions(exceptions): return decorator -def is_session_active(session): - """Return if the session is active - - Since sqlalchemy 1.4, "autocommit=False" by default; in sqlalchemy 2.0, - that will be the only possible value. If session autocommit is False, the - session transaction will not end at the end of a reader/writer context. - In this case, a session could have an active transaction even when it is - not inside a reader/writer context. In order to mimic the previous - behaviour, this method checks if there is a transaction created and if - the transaction has any active connection against the database server. - """ - if getattr(session, 'autocommit', None): - # old behaviour, to be removed with sqlalchemy 2.0 - return session.is_active - if not session.transaction: - return False - if not session.transaction._connections: - return False - return True - - def effective_qos_policy_id(resource): """Return the resource effective QoS policy diff --git a/neutron/db/db_base_plugin_v2.py b/neutron/db/db_base_plugin_v2.py index 04ef7b862be..9f4d33a1cec 100644 --- a/neutron/db/db_base_plugin_v2.py +++ b/neutron/db/db_base_plugin_v2.py @@ -428,7 +428,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, def update_network(self, context, id, network, db_network=None): n = network['network'] # we dont't use DB objects not belonging to the current active session - db_network = (db_network if utils.is_session_active(context.session) + db_network = (db_network if db_api.is_session_active(context.session) else None) with db_api.CONTEXT_WRITER.using(context): network = db_network or self._get_network(context, id) @@ -1500,7 +1500,8 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, @db_api.retry_if_session_inactive() def update_port(self, context, id, port, db_port=None): # we dont't use DB objects not belonging to the current active session - db_port = db_port if utils.is_session_active(context.session) else None + db_port = (db_port if db_api.is_session_active(context.session) + else None) new_port = port['port'] with db_api.CONTEXT_WRITER.using(context): diff --git a/neutron/db/l3_db.py b/neutron/db/l3_db.py index 6beeee0e664..2f8aabe9a35 100644 --- a/neutron/db/l3_db.py +++ b/neutron/db/l3_db.py @@ -260,7 +260,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, request_body, router_id): if gw_info: with db_utils.context_if_transaction( - context, not utils.is_session_active(context.session), + context, not db_api.is_session_active(context.session), writer=False): router_db = self._get_router(context, router_id) self._update_router_gw_info(context, router_id, @@ -344,7 +344,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, 'admin_state_up': True, 'name': ''} - if utils.is_session_active(context.session): + if db_api.is_session_active(context.session): # TODO(ralonsoh): ML2 plugin "create_port" should be called outside # a DB transaction. In this case an exception is made but in order # to prevent future errors, this call should be moved outside @@ -437,7 +437,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, gw_ips = [x['ip_address'] for x in router.gw_port['fixed_ips']] gw_port_id = router.gw_port['id'] self._delete_router_gw_port_db(context, router, request_body) - if utils.is_session_active(admin_ctx.session): + if db_api.is_session_active(admin_ctx.session): # TODO(ralonsoh): ML2 plugin "delete_port" should be called outside # a DB transaction. In this case an exception is made but in order # to prevent future errors, this call should be moved outside @@ -593,7 +593,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase, # transaction. router_ports_ids = (rp.port_id for rp in l3_obj.RouterPort.get_objects(context, router_id=id)) - if utils.is_session_active(context.session): + if db_api.is_session_active(context.session): context.GUARD_TRANSACTION = False for rp_id in router_ports_ids: self._core_plugin.delete_port(context.elevated(), rp_id, diff --git a/neutron/db/l3_hamode_db.py b/neutron/db/l3_hamode_db.py index eedace7fdde..4c26e5e5d7f 100644 --- a/neutron/db/l3_hamode_db.py +++ b/neutron/db/l3_hamode_db.py @@ -45,7 +45,6 @@ from sqlalchemy import exc as sql_exc from sqlalchemy import orm from neutron._i18n import _ -from neutron.common import utils from neutron.conf.db import l3_hamode_db from neutron.db import _utils as db_utils from neutron.db.availability_zone import router as router_az_db @@ -288,7 +287,7 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin, # the exception will mangle the state, cause the delete call to fail, # and end up relying on the DB rollback to remove the port instead of # proper delete_port call. - if utils.is_session_active(context.session): + if db_api.is_session_active(context.session): raise RuntimeError(_('add_ha_port cannot be called inside of a ' 'transaction.')) args = {'tenant_id': '', diff --git a/neutron/db/provisioning_blocks.py b/neutron/db/provisioning_blocks.py index b2ee4b201c5..cb4392c93d6 100644 --- a/neutron/db/provisioning_blocks.py +++ b/neutron/db/provisioning_blocks.py @@ -20,7 +20,6 @@ from neutron_lib.db import api as db_api from oslo_log import log as logging from neutron._i18n import _ -from neutron.common import utils from neutron.db import models_v2 from neutron.objects import provisioning_blocks as pb_obj @@ -125,7 +124,7 @@ def provisioning_complete(context, object_id, object_type, entity): log_dict = {'oid': object_id, 'entity': entity, 'otype': object_type} # this can't be called in a transaction to avoid REPEATABLE READ # tricking us into thinking there are remaining provisioning components - if utils.is_session_active(context.session): + if db_api.is_session_active(context.session): raise RuntimeError(_("Must not be called in a transaction")) with db_api.CONTEXT_WRITER.using(context): standard_attr_id = _get_standard_attr_id(context, object_id, diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py index c03f383da66..a50b998a920 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/mech_driver.py @@ -31,6 +31,7 @@ from neutron_lib.callbacks import registry from neutron_lib.callbacks import resources from neutron_lib import constants as const from neutron_lib import context as n_context +from neutron_lib.db import api as db_api from neutron_lib import exceptions as n_exc from neutron_lib.exceptions import availability_zone as az_exc from neutron_lib.placement import utils as place_utils @@ -50,7 +51,6 @@ from neutron.common.ovn import constants as ovn_const from neutron.common.ovn import exceptions as ovn_exceptions from neutron.common.ovn import extensions as ovn_extensions from neutron.common.ovn import utils as ovn_utils -from neutron.common import utils from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf from neutron.db import ovn_hash_ring_db from neutron.db import ovn_revision_numbers_db @@ -636,7 +636,7 @@ class OVNMechanismDriver(api.MechanismDriver): """ # FIXME(lucasagomes): We can delete this conditional after # https://bugs.launchpad.net/neutron/+bug/1739798 is fixed. - if utils.is_session_active(context._plugin_context.session): + if db_api.is_session_active(context._plugin_context.session): return self._ovn_client.update_network( context._plugin_context, context.current, diff --git a/neutron/plugins/ml2/ovo_rpc.py b/neutron/plugins/ml2/ovo_rpc.py index 6b0de780dee..a63998c1698 100644 --- a/neutron/plugins/ml2/ovo_rpc.py +++ b/neutron/plugins/ml2/ovo_rpc.py @@ -27,7 +27,6 @@ from oslo_log import log as logging from neutron.api.rpc.callbacks import events as rpc_events from neutron.api.rpc.handlers import resources_rpc -from neutron.common import utils from neutron.objects import address_group from neutron.objects import network from neutron.objects import ports @@ -79,7 +78,7 @@ class _ObjectChangeHandler(object): event transaction semantics are violated by other parts of the code. """ - if not utils.is_session_active(context.session): + if not db_api.is_session_active(context.session): return False if not self._semantic_warned: stack = traceback.extract_stack() diff --git a/neutron/tests/functional/common/test_utils.py b/neutron/tests/functional/common/test_utils.py index e61af645696..53a93dca265 100644 --- a/neutron/tests/functional/common/test_utils.py +++ b/neutron/tests/functional/common/test_utils.py @@ -42,13 +42,13 @@ class _TestIsSessionActive(testlib_api.SqlTestCase): def test_1(self): context = n_context.Context(user_id=None, tenant_id=None, is_admin=True, overwrite=False) - self.assertFalse(utils.is_session_active(context.session)) + self.assertFalse(db_api.is_session_active(context.session)) with db_api.CONTEXT_WRITER.using(context): net = models_v2.Network(id=uuidutils.generate_uuid()) context.session.add(net) - self.assertTrue(utils.is_session_active(context.session)) + self.assertTrue(db_api.is_session_active(context.session)) - self.assertFalse(utils.is_session_active(context.session)) + self.assertFalse(db_api.is_session_active(context.session)) class TestIsSessionActivePostgreSQL(testlib_api.PostgreSQLTestCaseMixin, diff --git a/neutron/tests/unit/plugins/ml2/test_plugin.py b/neutron/tests/unit/plugins/ml2/test_plugin.py index 73d82cf342d..143b8dc04b4 100644 --- a/neutron/tests/unit/plugins/ml2/test_plugin.py +++ b/neutron/tests/unit/plugins/ml2/test_plugin.py @@ -357,10 +357,10 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2, after = [] def b_func(r, c, v, payload=None): - before.append(utils.is_session_active(payload.context.session)) + before.append(db_api.is_session_active(payload.context.session)) def a_func(r, c, v, payload=None): - after.append(utils.is_session_active(payload.context.session)) + after.append(db_api.is_session_active(payload.context.session)) registry.subscribe(b_func, resources.NETWORK, events.BEFORE_CREATE) registry.subscribe(a_func, resources.NETWORK, events.AFTER_CREATE) @@ -1118,7 +1118,7 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): def receive(r, e, t, payload=None): setattr(self, 'tx_open', - utils.is_session_active(payload.context.session)) + db_api.is_session_active(payload.context.session)) registry.subscribe(receive, resources.PORT, events.AFTER_CREATE) with self.port(): @@ -1128,7 +1128,7 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): self.tx_open = True receive = lambda r, e, t, payload: \ setattr(self, 'tx_open', - utils.is_session_active(payload.context.session)) + db_api.is_session_active(payload.context.session)) with self.port() as p: registry.subscribe(receive, resources.PORT, events.AFTER_UPDATE) @@ -1140,7 +1140,7 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase): self.tx_open = True receive = lambda r, e, t, payload: \ setattr(self, 'tx_open', - utils.is_session_active(payload.context.session)) + db_api.is_session_active(payload.context.session)) with self.port() as p: registry.subscribe(receive, resources.PORT, events.AFTER_DELETE) diff --git a/neutron/tests/unit/plugins/ml2/test_security_group.py b/neutron/tests/unit/plugins/ml2/test_security_group.py index 1a83c77997e..3de28b62941 100644 --- a/neutron/tests/unit/plugins/ml2/test_security_group.py +++ b/neutron/tests/unit/plugins/ml2/test_security_group.py @@ -22,10 +22,10 @@ from neutron_lib.callbacks import registry from neutron_lib.callbacks import resources from neutron_lib import constants as const from neutron_lib import context +from neutron_lib.db import api as db_api from neutron_lib import fixture from neutron_lib.plugins import directory -from neutron.common import utils from neutron.extensions import securitygroup as ext_sg from neutron.tests.unit.agent import test_securitygroups_rpc as test_sg_rpc from neutron.tests.unit.api.v2 import test_base @@ -151,7 +151,7 @@ class TestMl2SecurityGroups(Ml2SecurityGroupsTestCase, def test_security_groups_created_outside_transaction(self): def record_after_state(r, e, t, payload=None): - self.was_active = utils.is_session_active(payload.context.session) + self.was_active = db_api.is_session_active(payload.context.session) registry.subscribe(record_after_state, resources.SECURITY_GROUP, events.AFTER_CREATE) diff --git a/neutron/tests/unit/services/revisions/test_revision_plugin.py b/neutron/tests/unit/services/revisions/test_revision_plugin.py index 2594f4f7499..ab29a09385d 100644 --- a/neutron/tests/unit/services/revisions/test_revision_plugin.py +++ b/neutron/tests/unit/services/revisions/test_revision_plugin.py @@ -23,7 +23,6 @@ from oslo_utils import uuidutils from sqlalchemy.orm import session as se from webob import exc -from neutron.common import utils from neutron.db import models_v2 from neutron.objects import ports as port_obj from neutron.tests.unit.plugins.ml2 import test_plugin @@ -60,7 +59,7 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase): # the new engine facade is resulting in changes being spread over # other sessions so we can end up getting stale reads in the parent # session if objects remain in the identity map. - if not utils.is_session_active(self._ctx.session): + if not db_api.is_session_active(self._ctx.session): self._ctx.session.expire_all() return self._ctx