Call target plugin out of DB transaction in the Metaplugin

Previously, there are cases that a target plugin is called
within a DB transaction in the metaplugin. This possibly causes
"DB lock timeout" error since a target plugin may take a long
time (ex. communicate to a controller).

Change-Id: Ie2971bfae1fecc97086b58cd943c321feb0aba04
Closes-Bug: #1267291
This commit is contained in:
Itsuro Oda 2014-02-05 10:12:26 +09:00
parent 00e19fb99b
commit e4389eb46f
2 changed files with 48 additions and 16 deletions

View File

@ -192,17 +192,16 @@ class MetaPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
if str(flavor) not in self.plugins:
flavor = self.default_flavor
plugin = self._get_plugin(flavor)
with context.session.begin(subtransactions=True):
net = plugin.create_network(context, network)
LOG.debug(_("Created network: %(net_id)s with flavor "
"%(flavor)s"), {'net_id': net['id'], 'flavor': flavor})
try:
meta_db_v2.add_network_flavor_binding(context.session,
flavor, str(net['id']))
except Exception:
LOG.exception(_('Failed to add flavor bindings'))
plugin.delete_network(context, net['id'])
raise FaildToAddFlavorBinding()
net = plugin.create_network(context, network)
LOG.debug(_("Created network: %(net_id)s with flavor "
"%(flavor)s"), {'net_id': net['id'], 'flavor': flavor})
try:
meta_db_v2.add_network_flavor_binding(context.session,
flavor, str(net['id']))
except Exception:
LOG.exception(_('Failed to add flavor bindings'))
plugin.delete_network(context, net['id'])
raise FaildToAddFlavorBinding()
LOG.debug(_("Created network: %s"), net['id'])
self._extend_network_dict(context, net)
@ -336,13 +335,17 @@ class MetaPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
if str(flavor) not in self.l3_plugins:
flavor = self.default_l3_flavor
plugin = self._get_l3_plugin(flavor)
with context.session.begin(subtransactions=True):
r_in_db = plugin.create_router(context, router)
LOG.debug(_("Created router: %(router_id)s with flavor "
"%(flavor)s"),
{'router_id': r_in_db['id'], 'flavor': flavor})
r_in_db = plugin.create_router(context, router)
LOG.debug(_("Created router: %(router_id)s with flavor "
"%(flavor)s"),
{'router_id': r_in_db['id'], 'flavor': flavor})
try:
meta_db_v2.add_router_flavor_binding(context.session,
flavor, str(r_in_db['id']))
except Exception:
LOG.exception(_('Failed to add flavor bindings'))
plugin.delete_router(context, r_in_db['id'])
raise FaildToAddFlavorBinding()
LOG.debug(_("Created router: %s"), r_in_db['id'])
self._extend_router_dict(context, r_in_db)

View File

@ -27,6 +27,8 @@ from neutron.db import db_base_plugin_v2
from neutron.db import models_v2
from neutron.extensions.flavor import (FLAVOR_NETWORK, FLAVOR_ROUTER)
from neutron.openstack.common import uuidutils
from neutron.plugins.metaplugin.meta_neutron_plugin import (
FaildToAddFlavorBinding)
from neutron.plugins.metaplugin.meta_neutron_plugin import FlavorNotFound
from neutron.plugins.metaplugin.meta_neutron_plugin import MetaPluginV2
from neutron.tests import base
@ -331,6 +333,30 @@ class MetaNeutronPluginV2Test(base.BaseTestCase):
self.fail("No Error is not raised")
def test_create_network_flavor_fail(self):
with mock.patch('neutron.plugins.metaplugin.meta_db_v2.'
'add_network_flavor_binding',
side_effect=Exception):
network = self._fake_network('fake1')
self.assertRaises(FaildToAddFlavorBinding,
self.plugin.create_network,
self.context,
network)
count = self.plugin.get_networks_count(self.context)
self.assertEqual(count, 0)
def test_create_router_flavor_fail(self):
with mock.patch('neutron.plugins.metaplugin.meta_db_v2.'
'add_router_flavor_binding',
side_effect=Exception):
router = self._fake_router('fake1')
self.assertRaises(FaildToAddFlavorBinding,
self.plugin.create_router,
self.context,
router)
count = self.plugin.get_routers_count(self.context)
self.assertEqual(count, 0)
class MetaNeutronPluginV2TestWithoutL3(MetaNeutronPluginV2Test):
"""Tests without l3_plugin_list configration."""
@ -343,3 +369,6 @@ class MetaNeutronPluginV2TestWithoutL3(MetaNeutronPluginV2Test):
def test_create_delete_router(self):
self.skipTest("Test case without router")
def test_create_router_flavor_fail(self):
self.skipTest("Test case without router")