Merge "Handle properly existing LLA address during l3 agent restart" into stable/stein

This commit is contained in:
Zuul 2020-08-28 17:57:48 +00:00 committed by Gerrit Code Review
commit 9f14638f61
2 changed files with 62 additions and 10 deletions

View File

@ -27,6 +27,7 @@ from oslo_utils import netutils
import six import six
from stevedore import driver from stevedore import driver
from neutron.agent.linux import ip_lib
from neutron.common import constants as l3_constants from neutron.common import constants as l3_constants
from neutron.common import utils from neutron.common import utils
@ -210,16 +211,20 @@ class PrefixDelegation(object):
def _add_lla(self, router, lla_with_mask): def _add_lla(self, router, lla_with_mask):
if router['gw_interface']: if router['gw_interface']:
self.intf_driver.add_ipv6_addr(router['gw_interface'], try:
lla_with_mask, self.intf_driver.add_ipv6_addr(router['gw_interface'],
router['ns_name'], lla_with_mask,
'link') router['ns_name'],
# There is a delay before the LLA becomes active. 'link')
# This is because the kernel runs DAD to make sure LLA uniqueness # There is a delay before the LLA becomes active.
# Spawn a thread to wait for the interface to be ready # This is because the kernel runs DAD to make sure LLA
self._spawn_lla_thread(router['gw_interface'], # uniqueness
router['ns_name'], # Spawn a thread to wait for the interface to be ready
lla_with_mask) self._spawn_lla_thread(router['gw_interface'],
router['ns_name'],
lla_with_mask)
except ip_lib.IpAddressAlreadyExists:
pass
def _spawn_lla_thread(self, gw_ifname, ns_name, lla_with_mask): def _spawn_lla_thread(self, gw_ifname, ns_name, lla_with_mask):
eventlet.spawn_n(self._ensure_lla_task, eventlet.spawn_n(self._ensure_lla_task,

View File

@ -3797,6 +3797,53 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
self._pd_assert_dibbler_calls(expected_calls, self._pd_assert_dibbler_calls(expected_calls,
self.external_process.mock_calls[-len(expected_calls):]) self.external_process.mock_calls[-len(expected_calls):])
@mock.patch.object(pd.PrefixDelegation, 'update_subnet')
@mock.patch.object(dibbler.PDDibbler, 'get_prefix', autospec=True)
@mock.patch.object(dibbler.os, 'getpid', return_value=1234)
@mock.patch.object(pd.PrefixDelegation, '_is_lla_active',
return_value=True)
@mock.patch.object(dibbler.os, 'chmod')
@mock.patch.object(dibbler.shutil, 'rmtree')
@mock.patch.object(pd.PrefixDelegation, '_get_sync_data')
def test_pd_lla_already_exists(self, mock1, mock2, mock3, mock4,
mock_getpid, mock_get_prefix,
mock_pd_update_subnet):
'''Test HA in the active router
The intent is to test the PD code with HA. To avoid unnecessary
complexities, use the regular router.
'''
# Initial setup
agent, router, ri = self._pd_setup_agent_router(enable_ha=True)
agent.pd.intf_driver = mock.MagicMock()
agent.pd.intf_driver.add_ipv6_addr.side_effect = (
ip_lib.IpAddressAlreadyExists())
# Create one pd-enabled subnet and add router interface
l3_test_common.router_append_pd_enabled_subnet(router)
self._pd_add_gw_interface(agent, ri)
ri.process()
# No client should be started since it's standby router
agent.pd.process_prefix_update()
self.assertFalse(self.external_process.called)
self.assertFalse(mock_get_prefix.called)
update_router = copy.deepcopy(router)
pd_intfs = l3_test_common.get_unassigned_pd_interfaces(update_router)
# Turn the router to be active
agent.pd.process_ha_state(router['id'], True)
# Get prefixes
self._pd_get_prefixes(agent, ri, [], pd_intfs, mock_get_prefix)
# Update the router with the new prefix
ri.router = update_router
ri.process()
self._pd_verify_update_results(ri, pd_intfs, mock_pd_update_subnet)
@mock.patch.object(dibbler.os, 'chmod') @mock.patch.object(dibbler.os, 'chmod')
def test_pd_generate_dibbler_conf(self, mock_chmod): def test_pd_generate_dibbler_conf(self, mock_chmod):
pddib = dibbler.PDDibbler("router_id", "subnet-id", "ifname") pddib = dibbler.PDDibbler("router_id", "subnet-id", "ifname")