Fix Rollback port's device_owner

From this patch: https://review.openstack.org/#/c/341427/
Sometimes, port doesn't revert device_owner to previous value
in concurrent requests case.

This patch fixes this problem and adds unit test.

Change-Id: I864a559f0316e164caa065abd75c44fae971b571
Closes-Bug: #1621750
This commit is contained in:
Anh Tran 2016-09-09 11:18:18 +07:00
parent dc6e83771c
commit 5f9d888707
3 changed files with 51 additions and 4 deletions

View File

@ -802,13 +802,13 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
port, subnets, new_port = self._add_interface_by_subnet(
context, router, interface_info['subnet_id'], device_owner)
cleanup_port = new_port # only cleanup port we created
revert_value = {'device_id': '',
'device_owner': port['device_owner']}
if cleanup_port:
mgr = p_utils.delete_port_on_error(
self._core_plugin, context, port['id'])
else:
revert_value = {'device_id': '',
'device_owner': port['device_owner']}
mgr = p_utils.update_port_on_error(
self._core_plugin, context, port['id'], revert_value)

View File

@ -327,6 +327,8 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
port, subnets, new_port = self._add_interface_by_subnet(
context, router, interface_info['subnet_id'], device_owner)
cleanup_port = new_port
revert_value = {'device_id': '',
'device_owner': port['device_owner']}
subnet = subnets[0]
@ -334,8 +336,6 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
mgr = p_utils.delete_port_on_error(
self._core_plugin, context, port['id'])
else:
revert_value = {'device_id': '',
'device_owner': port['device_owner']}
mgr = p_utils.update_port_on_error(
self._core_plugin, context, port['id'], revert_value)

View File

@ -52,6 +52,10 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
with self.ctx.session.begin(subtransactions=True):
return self.mixin._create_router_db(self.ctx, router, 'foo_tenant')
def create_port(self, net_id, port_info):
with self.ctx.session.begin(subtransactions=True):
return self._create_port(self.fmt, net_id, **port_info)
def _test__create_router_db(self, expected=False, distributed=None):
router = {'name': 'foo_router', 'admin_state_up': True}
if distributed is not None:
@ -725,3 +729,46 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
self.assertEqual(1, len(router_ports))
self.assertEqual(l3_const.DEVICE_OWNER_ROUTER_GW,
router_ports[0]['device_owner'])
def test_add_router_interface_by_port_failure(self):
router_dict = {'name': 'test_router',
'admin_state_up': True,
'distributed': True}
router = self._create_router(router_dict)
with self.subnet(cidr='10.10.10.0/24') as subnet:
port_dict = {
'device_id': '',
'device_owner': '',
'admin_state_up': True,
'fixed_ips': [{'subnet_id': subnet['subnet']['id'],
'ip_address': '10.10.10.100'}]
}
net_id = subnet['subnet']['network_id']
port_res = self.create_port(net_id, port_dict)
port = self.deserialize(self.fmt, port_res)
self.assertIn('port', port, message='Create port failed.')
orig_update_port = self.mixin._core_plugin.update_port
call_info = {'count': 0}
def _fake_update_port(*args, **kwargs):
call_info['count'] += 1
if call_info['count'] == 2:
raise RuntimeError()
else:
return orig_update_port(*args, **kwargs)
# NOTE(trananhkma): expect that update_port() only raises an error
# at the 2nd function call (Update owner after actual process
# again in order).
with mock.patch.object(self.mixin._core_plugin, 'update_port',
side_effect=_fake_update_port):
self.assertRaises(
RuntimeError,
self.mixin.add_router_interface,
self.ctx, router['id'], {'port_id': port['port']['id']})
port_info = self.core_plugin.get_port(self.ctx, port['port']['id'])
self.assertEqual(port_dict['device_id'], port_info['device_id'])
self.assertEqual(port_dict['device_owner'],
port_info['device_owner'])