Browse Source

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

changes/60/748960/1
Zuul 11 months ago
committed by Gerrit Code Review
parent
commit
9f14638f61
  1. 25
      neutron/agent/linux/pd.py
  2. 47
      neutron/tests/unit/agent/l3/test_agent.py

25
neutron/agent/linux/pd.py

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

47
neutron/tests/unit/agent/l3/test_agent.py

@ -3797,6 +3797,53 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
self._pd_assert_dibbler_calls(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')
def test_pd_generate_dibbler_conf(self, mock_chmod):
pddib = dibbler.PDDibbler("router_id", "subnet-id", "ifname")

Loading…
Cancel
Save