Use neutron-lib method is_session_active

In patch [1] temporary was added is_session_active
method before n-lib patch [2] release. Now modified to
n-lib method

1) https://review.opendev.org/c/openstack/neutron/+/828739
2) https://review.opendev.org/c/openstack/neutron-lib/+/828738

Change-Id: I1144215b72f7c435e1949b2d66f8bbb268b08c98
This commit is contained in:
Nurmatov Mamatisa 2022-07-27 11:18:16 +03:00 committed by Rodolfo Alonso Hernandez
parent 3e8f2325d6
commit 655001594b
11 changed files with 24 additions and 48 deletions

View File

@ -695,7 +695,7 @@ def transaction_guard(f):
n_context.ContextBaseWithSession) else n_context.ContextBaseWithSession) else
args[1]) args[1])
# FIXME(kevinbenton): get rid of all uses of this flag # 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)): getattr(context, 'GUARD_TRANSACTION', True)):
raise RuntimeError(_("Method %s cannot be called within a " raise RuntimeError(_("Method %s cannot be called within a "
"transaction.") % f) "transaction.") % f)
@ -1029,27 +1029,6 @@ def skip_exceptions(exceptions):
return decorator 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): def effective_qos_policy_id(resource):
"""Return the resource effective QoS policy """Return the resource effective QoS policy

View File

@ -428,7 +428,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
def update_network(self, context, id, network, db_network=None): def update_network(self, context, id, network, db_network=None):
n = network['network'] n = network['network']
# we dont't use DB objects not belonging to the current active session # 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) else None)
with db_api.CONTEXT_WRITER.using(context): with db_api.CONTEXT_WRITER.using(context):
network = db_network or self._get_network(context, id) 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() @db_api.retry_if_session_inactive()
def update_port(self, context, id, port, db_port=None): def update_port(self, context, id, port, db_port=None):
# we dont't use DB objects not belonging to the current active session # 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'] new_port = port['port']
with db_api.CONTEXT_WRITER.using(context): with db_api.CONTEXT_WRITER.using(context):

View File

@ -260,7 +260,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
request_body, router_id): request_body, router_id):
if gw_info: if gw_info:
with db_utils.context_if_transaction( 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): writer=False):
router_db = self._get_router(context, router_id) router_db = self._get_router(context, router_id)
self._update_router_gw_info(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, 'admin_state_up': True,
'name': ''} '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 # TODO(ralonsoh): ML2 plugin "create_port" should be called outside
# a DB transaction. In this case an exception is made but in order # a DB transaction. In this case an exception is made but in order
# to prevent future errors, this call should be moved outside # 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_ips = [x['ip_address'] for x in router.gw_port['fixed_ips']]
gw_port_id = router.gw_port['id'] gw_port_id = router.gw_port['id']
self._delete_router_gw_port_db(context, router, request_body) 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 # TODO(ralonsoh): ML2 plugin "delete_port" should be called outside
# a DB transaction. In this case an exception is made but in order # a DB transaction. In this case an exception is made but in order
# to prevent future errors, this call should be moved outside # to prevent future errors, this call should be moved outside
@ -593,7 +593,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
# transaction. # transaction.
router_ports_ids = (rp.port_id for rp in router_ports_ids = (rp.port_id for rp in
l3_obj.RouterPort.get_objects(context, router_id=id)) 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 context.GUARD_TRANSACTION = False
for rp_id in router_ports_ids: for rp_id in router_ports_ids:
self._core_plugin.delete_port(context.elevated(), rp_id, self._core_plugin.delete_port(context.elevated(), rp_id,

View File

@ -45,7 +45,6 @@ from sqlalchemy import exc as sql_exc
from sqlalchemy import orm from sqlalchemy import orm
from neutron._i18n import _ from neutron._i18n import _
from neutron.common import utils
from neutron.conf.db import l3_hamode_db from neutron.conf.db import l3_hamode_db
from neutron.db import _utils as db_utils from neutron.db import _utils as db_utils
from neutron.db.availability_zone import router as router_az_db 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, # 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 # and end up relying on the DB rollback to remove the port instead of
# proper delete_port call. # 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 ' raise RuntimeError(_('add_ha_port cannot be called inside of a '
'transaction.')) 'transaction.'))
args = {'tenant_id': '', args = {'tenant_id': '',

View File

@ -20,7 +20,6 @@ from neutron_lib.db import api as db_api
from oslo_log import log as logging from oslo_log import log as logging
from neutron._i18n import _ from neutron._i18n import _
from neutron.common import utils
from neutron.db import models_v2 from neutron.db import models_v2
from neutron.objects import provisioning_blocks as pb_obj 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} log_dict = {'oid': object_id, 'entity': entity, 'otype': object_type}
# this can't be called in a transaction to avoid REPEATABLE READ # this can't be called in a transaction to avoid REPEATABLE READ
# tricking us into thinking there are remaining provisioning components # 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")) raise RuntimeError(_("Must not be called in a transaction"))
with db_api.CONTEXT_WRITER.using(context): with db_api.CONTEXT_WRITER.using(context):
standard_attr_id = _get_standard_attr_id(context, object_id, standard_attr_id = _get_standard_attr_id(context, object_id,

View File

@ -31,6 +31,7 @@ from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources from neutron_lib.callbacks import resources
from neutron_lib import constants as const from neutron_lib import constants as const
from neutron_lib import context as n_context 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 import exceptions as n_exc
from neutron_lib.exceptions import availability_zone as az_exc from neutron_lib.exceptions import availability_zone as az_exc
from neutron_lib.placement import utils as place_utils 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 exceptions as ovn_exceptions
from neutron.common.ovn import extensions as ovn_extensions from neutron.common.ovn import extensions as ovn_extensions
from neutron.common.ovn import utils as ovn_utils 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.conf.plugins.ml2.drivers.ovn import ovn_conf
from neutron.db import ovn_hash_ring_db from neutron.db import ovn_hash_ring_db
from neutron.db import ovn_revision_numbers_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 # FIXME(lucasagomes): We can delete this conditional after
# https://bugs.launchpad.net/neutron/+bug/1739798 is fixed. # 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 return
self._ovn_client.update_network( self._ovn_client.update_network(
context._plugin_context, context.current, context._plugin_context, context.current,

View File

@ -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.callbacks import events as rpc_events
from neutron.api.rpc.handlers import resources_rpc from neutron.api.rpc.handlers import resources_rpc
from neutron.common import utils
from neutron.objects import address_group from neutron.objects import address_group
from neutron.objects import network from neutron.objects import network
from neutron.objects import ports from neutron.objects import ports
@ -79,7 +78,7 @@ class _ObjectChangeHandler(object):
event transaction semantics are violated by other parts of event transaction semantics are violated by other parts of
the code. the code.
""" """
if not utils.is_session_active(context.session): if not db_api.is_session_active(context.session):
return False return False
if not self._semantic_warned: if not self._semantic_warned:
stack = traceback.extract_stack() stack = traceback.extract_stack()

View File

@ -42,13 +42,13 @@ class _TestIsSessionActive(testlib_api.SqlTestCase):
def test_1(self): def test_1(self):
context = n_context.Context(user_id=None, tenant_id=None, context = n_context.Context(user_id=None, tenant_id=None,
is_admin=True, overwrite=False) 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): with db_api.CONTEXT_WRITER.using(context):
net = models_v2.Network(id=uuidutils.generate_uuid()) net = models_v2.Network(id=uuidutils.generate_uuid())
context.session.add(net) 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, class TestIsSessionActivePostgreSQL(testlib_api.PostgreSQLTestCaseMixin,

View File

@ -357,10 +357,10 @@ class TestMl2NetworksV2(test_plugin.TestNetworksV2,
after = [] after = []
def b_func(r, c, v, payload=None): 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): 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(b_func, resources.NETWORK, events.BEFORE_CREATE)
registry.subscribe(a_func, resources.NETWORK, events.AFTER_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): def receive(r, e, t, payload=None):
setattr(self, 'tx_open', 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) registry.subscribe(receive, resources.PORT, events.AFTER_CREATE)
with self.port(): with self.port():
@ -1128,7 +1128,7 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase):
self.tx_open = True self.tx_open = True
receive = lambda r, e, t, payload: \ receive = lambda r, e, t, payload: \
setattr(self, 'tx_open', setattr(self, 'tx_open',
utils.is_session_active(payload.context.session)) db_api.is_session_active(payload.context.session))
with self.port() as p: with self.port() as p:
registry.subscribe(receive, resources.PORT, events.AFTER_UPDATE) registry.subscribe(receive, resources.PORT, events.AFTER_UPDATE)
@ -1140,7 +1140,7 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase):
self.tx_open = True self.tx_open = True
receive = lambda r, e, t, payload: \ receive = lambda r, e, t, payload: \
setattr(self, 'tx_open', setattr(self, 'tx_open',
utils.is_session_active(payload.context.session)) db_api.is_session_active(payload.context.session))
with self.port() as p: with self.port() as p:
registry.subscribe(receive, resources.PORT, events.AFTER_DELETE) registry.subscribe(receive, resources.PORT, events.AFTER_DELETE)

View File

@ -22,10 +22,10 @@ from neutron_lib.callbacks import registry
from neutron_lib.callbacks import resources from neutron_lib.callbacks import resources
from neutron_lib import constants as const from neutron_lib import constants as const
from neutron_lib import context from neutron_lib import context
from neutron_lib.db import api as db_api
from neutron_lib import fixture from neutron_lib import fixture
from neutron_lib.plugins import directory from neutron_lib.plugins import directory
from neutron.common import utils
from neutron.extensions import securitygroup as ext_sg 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.agent import test_securitygroups_rpc as test_sg_rpc
from neutron.tests.unit.api.v2 import test_base 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 test_security_groups_created_outside_transaction(self):
def record_after_state(r, e, t, payload=None): 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, registry.subscribe(record_after_state, resources.SECURITY_GROUP,
events.AFTER_CREATE) events.AFTER_CREATE)

View File

@ -23,7 +23,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.common import utils
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
@ -60,7 +59,7 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase):
# the new engine facade is resulting in changes being spread over # the new engine facade is resulting in changes being spread over
# other sessions so we can end up getting stale reads in the parent # other sessions so we can end up getting stale reads in the parent
# session if objects remain in the identity map. # 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() self._ctx.session.expire_all()
return self._ctx return self._ctx