From 622dea818d851224a43d5276a81d5ce8a6eebb76 Mon Sep 17 00:00:00 2001 From: Ivar Lazzaro Date: Mon, 17 Aug 2015 17:17:42 -0700 Subject: [PATCH] handle gw_info outside of the db transaction on router creation Move the gateway interface creation outside the DB transaction to avoid lock timeout. Change-Id: I5a78d7f32e8ca912016978105221d5f34618af19 Closes-bug: 1485809 --- neutron/db/l3_db.py | 10 ++++++++-- neutron/tests/unit/extensions/test_l3.py | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/neutron/db/l3_db.py b/neutron/db/l3_db.py index ebd7465e8..a803dcb61 100644 --- a/neutron/db/l3_db.py +++ b/neutron/db/l3_db.py @@ -174,11 +174,17 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase): r = router['router'] gw_info = r.pop(EXTERNAL_GW_INFO, None) tenant_id = self._get_tenant_id_for_create(context, r) - with context.session.begin(subtransactions=True): - router_db = self._create_router_db(context, r, tenant_id) + router_db = self._create_router_db(context, r, tenant_id) + try: if gw_info: self._update_router_gw_info(context, router_db['id'], gw_info, router=router_db) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.exception(_LE("An exception occurred while creating " + "the router: %s"), router) + self.delete_router(context, router_db.id) + return self._make_router_dict(router_db) def _update_router_db(self, context, router_id, data, gw_info): diff --git a/neutron/tests/unit/extensions/test_l3.py b/neutron/tests/unit/extensions/test_l3.py index 77e55682b..7c6f47cad 100644 --- a/neutron/tests/unit/extensions/test_l3.py +++ b/neutron/tests/unit/extensions/test_l3.py @@ -2477,6 +2477,23 @@ class L3NatTestCaseBase(L3NatTestCaseMixin): fip['floatingip']['floating_ip_address']) self.assertEqual(floating_ip.version, 4) + def test_create_router_gateway_fails(self): + # Force _update_router_gw_info failure + plugin = manager.NeutronManager.get_service_plugins()[ + service_constants.L3_ROUTER_NAT] + ctx = context.Context('', 'foo') + plugin._update_router_gw_info = mock.Mock( + side_effect=n_exc.NeutronException) + data = {'router': { + 'name': 'router1', 'admin_state_up': True, + 'external_gateway_info': {'network_id': 'some_uuid'}}} + + # Verify router doesn't persist on failure + self.assertRaises(n_exc.NeutronException, + plugin.create_router, ctx, data) + routers = plugin.get_routers(ctx) + self.assertEqual(0, len(routers)) + class L3AgentDbTestCaseBase(L3NatTestCaseMixin): -- 2.45.2