# License for the specific language governing permissions and limitations
# under the License.
+import contextlib
+
from six import moves
import sqlalchemy
from sqlalchemy.orm import properties
query = query.limit(limit)
return query
+
+
+default_tx_isolation_level = None
+
+
+def get_default_tx_level(engine):
+ global default_tx_isolation_level
+ if not default_tx_isolation_level:
+ default_tx_isolation_level = engine.dialect.get_isolation_level(
+ engine.raw_connection())
+ return default_tx_isolation_level
+
+
+@contextlib.contextmanager
+def set_mysql_tx_isolation_level(session, level):
+ engine = session.connection().engine
+ if (engine.name == "mysql" and level != get_default_tx_level(engine)):
+ session.connection().execution_options(
+ isolation_level=level)
+ yield
+ engine = session.connection().engine
+ if engine.name == "mysql":
+ session.connection().execution_options(
+ isolation_level=get_default_tx_level(engine))
from neutron.db import models_v2
from neutron.db import quota_db # noqa
from neutron.db import securitygroups_rpc_base as sg_db_rpc
+from neutron.db import sqlalchemyutils as sqla
from neutron.extensions import allowedaddresspairs as addr_pair
from neutron.extensions import extra_dhcp_opt as edo_ext
from neutron.extensions import l3agentscheduler
net_data = network[attributes.NETWORK]
tenant_id = self._get_tenant_id_for_create(context, net_data)
session = context.session
- with session.begin(subtransactions=True):
+ with contextlib.nested(
+ session.begin(subtransactions=True),
+ sqla.set_mysql_tx_isolation_level(session, "READ COMMITTED")
+ ):
self._ensure_default_security_group(context, tenant_id)
result = super(Ml2Plugin, self).create_network(context, network)
self.extension_manager.process_create_network(session, net_data,
--- /dev/null
+# Copyright (c) 2014 OpenStack Foundation.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import contextlib
+
+from oslo.config import cfg
+from oslo.db.sqlalchemy import test_base
+
+from neutron import context
+from neutron.db import sqlalchemyutils
+from neutron.tests import base
+
+
+class TestSettingTXIsolationLevel(base.BaseTestCase,
+ test_base.MySQLOpportunisticTestCase):
+ """Check that transaction isolation level indeed changes."""
+
+ def setUp(self):
+ super(TestSettingTXIsolationLevel, self).setUp()
+ cfg.CONF.set_override('connection',
+ self.engine.url,
+ group='database')
+
+ def _get_session_tx_isolation(self, session):
+ sql = "SELECT @@tx_isolation;"
+ res = session.connection().execute(sql)
+ res = [r for r in res]
+ res = [r for r in res[0]]
+ return res[0]
+
+ def test_set_tx_iso_level_changes_back_and_forth_mysql(self):
+ ctx = context.get_admin_context()
+ default_level = sqlalchemyutils.get_default_tx_level(self.engine)
+ other_level = ("READ COMMITTED" if default_level == "REPEATABLE READ"
+ else "REPEATABLE READ")
+ with contextlib.nested(
+ ctx.session.begin(subtransactions=True),
+ sqlalchemyutils.set_mysql_tx_isolation_level(
+ ctx.session, other_level)
+ ):
+ res = self._get_session_tx_isolation(ctx.session)
+ self.assertEqual(other_level.replace(' ', '-'), res)
+ #check that context manager changes tx isolation level back
+ res = self._get_session_tx_isolation(ctx.session)
+ self.assertEqual(default_level.replace(' ', '-'), res)