Merge "Enable ipv6_forwarding in HA router's namespace" into stable/queens

This commit is contained in:
Zuul 2019-03-18 17:23:26 +00:00 committed by Gerrit Code Review
commit ea3bcca169
4 changed files with 80 additions and 35 deletions

View File

@ -121,7 +121,7 @@ class AgentMixin(object):
# configuration to keepalived-state-change in order to remove the # configuration to keepalived-state-change in order to remove the
# dependency that currently exists on l3-agent running for the IPv6 # dependency that currently exists on l3-agent running for the IPv6
# failover. # failover.
self._configure_ipv6_params_on_ext_gw_port_if_necessary(ri, state) self._configure_ipv6_params(ri, state)
if self.conf.enable_metadata_proxy: if self.conf.enable_metadata_proxy:
self._update_metadata_proxy(ri, router_id, state) self._update_metadata_proxy(ri, router_id, state)
self._update_radvd_daemon(ri, state) self._update_radvd_daemon(ri, state)
@ -129,25 +129,31 @@ class AgentMixin(object):
self.state_change_notifier.queue_event((router_id, state)) self.state_change_notifier.queue_event((router_id, state))
self.l3_ext_manager.ha_state_change(self.context, state_change_data) self.l3_ext_manager.ha_state_change(self.context, state_change_data)
def _configure_ipv6_params_on_ext_gw_port_if_necessary(self, ri, state): def _configure_ipv6_params(self, ri, state):
if not self.use_ipv6:
return
ipv6_forwarding_enable = state == 'master'
if ri.router.get('distributed', False):
namespace = ri.ha_namespace
else:
namespace = ri.ns_name
if ipv6_forwarding_enable:
ri.driver.configure_ipv6_forwarding(
namespace, 'all', ipv6_forwarding_enable)
# If ipv6 is enabled on the platform, ipv6_gateway config flag is # If ipv6 is enabled on the platform, ipv6_gateway config flag is
# not set and external_network associated to the router does not # not set and external_network associated to the router does not
# include any IPv6 subnet, enable the gateway interface to accept # include any IPv6 subnet, enable the gateway interface to accept
# Router Advts from upstream router for default route on master # Router Advts from upstream router for default route on master
# instances as well as ipv6 forwarding. Otherwise, disable them. # instances as well as ipv6 forwarding. Otherwise, disable them.
ex_gw_port_id = ri.ex_gw_port and ri.ex_gw_port['id'] ex_gw_port_id = ri.ex_gw_port and ri.ex_gw_port['id']
if not ex_gw_port_id: if ex_gw_port_id:
return interface_name = ri.get_external_device_name(ex_gw_port_id)
ri._configure_ipv6_params_on_gw(
interface_name = ri.get_external_device_name(ex_gw_port_id) ri.ex_gw_port, namespace, interface_name,
if ri.router.get('distributed', False): ipv6_forwarding_enable)
namespace = ri.ha_namespace
else:
namespace = ri.ns_name
enable = state == 'master'
ri._configure_ipv6_params_on_gw(ri.ex_gw_port, namespace,
interface_name, enable)
def _update_metadata_proxy(self, ri, router_id, state): def _update_metadata_proxy(self, ri, router_id, state):
# NOTE(slaweq): Since the metadata proxy is spawned in the qrouter # NOTE(slaweq): Since the metadata proxy is spawned in the qrouter

View File

@ -112,7 +112,8 @@ class L3AgentTestFramework(base.BaseSudoTestCase):
def generate_router_info(self, enable_ha, ip_version=4, extra_routes=True, def generate_router_info(self, enable_ha, ip_version=4, extra_routes=True,
enable_fip=True, enable_snat=True, enable_fip=True, enable_snat=True,
num_internal_ports=1, num_internal_ports=1,
dual_stack=False, v6_ext_gw_with_sub=True, dual_stack=False, enable_gw=True,
v6_ext_gw_with_sub=True,
qos_policy_id=None): qos_policy_id=None):
if ip_version == 6 and not dual_stack: if ip_version == 6 and not dual_stack:
enable_snat = False enable_snat = False
@ -127,6 +128,7 @@ class L3AgentTestFramework(base.BaseSudoTestCase):
enable_ha=enable_ha, enable_ha=enable_ha,
extra_routes=extra_routes, extra_routes=extra_routes,
dual_stack=dual_stack, dual_stack=dual_stack,
enable_gw=enable_gw,
v6_ext_gw_with_sub=( v6_ext_gw_with_sub=(
v6_ext_gw_with_sub), v6_ext_gw_with_sub),
qos_policy_id=qos_policy_id) qos_policy_id=qos_policy_id)

View File

@ -116,8 +116,11 @@ class L3HATestCase(framework.L3AgentTestFramework):
router_info['gw_port'] = ex_port router_info['gw_port'] = ex_port
router.process() router.process()
self._assert_ipv6_accept_ra(router, expected_ra) self._assert_ipv6_accept_ra(router, expected_ra)
# As router is going first to master and than to backup mode,
# ipv6_forwarding should be enabled on "all" interface always after
# that transition
self._assert_ipv6_forwarding(router, expected_forwarding, self._assert_ipv6_forwarding(router, expected_forwarding,
expected_forwarding) True)
@testtools.skipUnless(ipv6_utils.is_enabled_and_bind_by_default(), @testtools.skipUnless(ipv6_utils.is_enabled_and_bind_by_default(),
"IPv6 is not enabled") "IPv6 is not enabled")
@ -358,6 +361,24 @@ class L3HATestCase(framework.L3AgentTestFramework):
self._wait_until_ipv6_forwarding_has_state( self._wait_until_ipv6_forwarding_has_state(
router.ns_name, external_device_name, 1) router.ns_name, external_device_name, 1)
@testtools.skipUnless(ipv6_utils.is_enabled_and_bind_by_default(),
"IPv6 is not enabled")
def test_ha_router_without_gw_ipv6_forwarding_state(self):
router_info = self.generate_router_info(
enable_ha=True, enable_gw=False)
router_info[constants.HA_INTERFACE_KEY]['status'] = (
constants.PORT_STATUS_DOWN)
router = self.manage_router(self.agent, router_info)
common_utils.wait_until_true(lambda: router.ha_state == 'backup')
self._wait_until_ipv6_forwarding_has_state(router.ns_name, 'all', 0)
router.router[constants.HA_INTERFACE_KEY]['status'] = (
constants.PORT_STATUS_ACTIVE)
self.agent._process_updated_router(router.router)
common_utils.wait_until_true(lambda: router.ha_state == 'master')
self._wait_until_ipv6_forwarding_has_state(router.ns_name, 'all', 1)
class L3HATestFailover(framework.L3AgentTestFramework): class L3HATestFailover(framework.L3AgentTestFramework):
@ -400,7 +421,7 @@ class L3HATestFailover(framework.L3AgentTestFramework):
self._assert_ipv6_forwarding(new_master, True, True) self._assert_ipv6_forwarding(new_master, True, True)
self._assert_ipv6_accept_ra(new_slave, False) self._assert_ipv6_accept_ra(new_slave, False)
# after transition from master -> slave, 'all' IPv6 forwarding should # after transition from master -> slave, 'all' IPv6 forwarding should
# still be enabled # be enabled
self._assert_ipv6_forwarding(new_slave, False, True) self._assert_ipv6_forwarding(new_slave, False, True)
def test_ha_router_lost_gw_connection(self): def test_ha_router_lost_gw_connection(self):

View File

@ -269,29 +269,45 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
spawn_metadata_proxy.assert_called() spawn_metadata_proxy.assert_called()
destroy_metadata_proxy.assert_not_called() destroy_metadata_proxy.assert_not_called()
def _test__configure_ipv6_params_on_ext_gw_port_if_necessary_helper( def _test__configure_ipv6_params_helper(self, state, gw_port_id):
self, state, enable_expected):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
router_info = l3router.RouterInfo(agent, _uuid(), {}, **self.ri_kwargs) router_info = l3router.RouterInfo(agent, _uuid(), {}, **self.ri_kwargs)
router_info.ex_gw_port = {'id': _uuid()} if gw_port_id:
with mock.patch.object(router_info, '_configure_ipv6_params_on_gw' router_info.ex_gw_port = {'id': gw_port_id}
) as mock_configure_ipv6: expected_forwarding_state = state == 'master'
agent._configure_ipv6_params_on_ext_gw_port_if_necessary( with mock.patch.object(
router_info, state) router_info.driver, "configure_ipv6_forwarding"
interface_name = router_info.get_external_device_name( ) as configure_ipv6_forwarding, mock.patch.object(
router_info.ex_gw_port['id']) router_info, "_configure_ipv6_params_on_gw"
) as configure_ipv6_on_gw:
agent._configure_ipv6_params(router_info, state)
mock_configure_ipv6.assert_called_once_with( if state == 'master':
router_info.ex_gw_port, router_info.ns_name, interface_name, configure_ipv6_forwarding.assert_called_once_with(
enable_expected) router_info.ns_name, 'all', expected_forwarding_state)
else:
configure_ipv6_forwarding.assert_not_called()
def test__configure_ipv6_params_on_ext_gw_port_if_necessary_master(self): if gw_port_id:
self._test__configure_ipv6_params_on_ext_gw_port_if_necessary_helper( interface_name = router_info.get_external_device_name(
'master', True) router_info.ex_gw_port['id'])
configure_ipv6_on_gw.assert_called_once_with(
router_info.ex_gw_port, router_info.ns_name,
interface_name, expected_forwarding_state)
else:
configure_ipv6_on_gw.assert_not_called()
def test__configure_ipv6_params_on_ext_gw_port_if_necessary_backup(self): def test__configure_ipv6_params_master(self):
self._test__configure_ipv6_params_on_ext_gw_port_if_necessary_helper( self._test__configure_ipv6_params_helper('master', gw_port_id=_uuid())
'backup', False)
def test__configure_ipv6_params_backup(self):
self._test__configure_ipv6_params_helper('backup', gw_port_id=_uuid())
def test__configure_ipv6_params_master_no_gw_port(self):
self._test__configure_ipv6_params_helper('master', gw_port_id=None)
def test__configure_ipv6_params_backup_no_gw_port(self):
self._test__configure_ipv6_params_helper('backup', gw_port_id=None)
def test_check_ha_state_for_router_master_standby(self): def test_check_ha_state_for_router_master_standby(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)