Merge "Add 'keepalived_use_no_track' config option" into stable/rocky

This commit is contained in:
Zuul 2020-09-04 03:27:32 +00:00 committed by Gerrit Code Review
commit 10c56c0cda
7 changed files with 132 additions and 17 deletions

View File

@ -105,7 +105,7 @@ class KeepalivedVipAddress(object):
result = '%s dev %s' % (self.ip_address, self.interface_name) result = '%s dev %s' % (self.ip_address, self.interface_name)
if self.scope: if self.scope:
result += ' scope %s' % self.scope result += ' scope %s' % self.scope
if not self.track: if cfg.CONF.keepalived_use_no_track and not self.track:
result += ' no_track' result += ' no_track'
return result return result
@ -128,7 +128,8 @@ class KeepalivedVirtualRoute(object):
output += ' dev %s' % self.interface_name output += ' dev %s' % self.interface_name
if self.scope: if self.scope:
output += ' scope %s' % self.scope output += ' scope %s' % self.scope
output += ' no_track' if cfg.CONF.keepalived_use_no_track:
output += ' no_track'
return output return output

View File

@ -34,6 +34,7 @@ from neutron.agent.linux import utils as agent_utils
from neutron.cmd import runtime_checks from neutron.cmd import runtime_checks
from neutron.common import constants from neutron.common import constants
from neutron.common import utils as common_utils from neutron.common import utils as common_utils
from neutron.conf.agent.l3 import config as l3_config
from neutron.plugins.ml2.drivers.openvswitch.agent.common \ from neutron.plugins.ml2.drivers.openvswitch.agent.common \
import constants as ovs_const import constants as ovs_const
@ -250,6 +251,7 @@ def bridge_firewalling_enabled():
class KeepalivedIPv6Test(object): class KeepalivedIPv6Test(object):
def __init__(self, ha_port, gw_port, gw_vip, default_gw): def __init__(self, ha_port, gw_port, gw_vip, default_gw):
l3_config.register_l3_agent_config_opts(l3_config.OPTS, cfg.CONF)
self.ha_port = ha_port self.ha_port = ha_port
self.gw_port = gw_port self.gw_port = gw_port
self.gw_vip = gw_vip self.gw_vip = gw_vip

View File

@ -109,6 +109,12 @@ OPTS = [
'(by default), the user executing the L3 agent will be ' '(by default), the user executing the L3 agent will be '
'passed. If "root" specified, because radvd is spawned ' 'passed. If "root" specified, because radvd is spawned '
'as root, no "username" parameter will be passed.')), 'as root, no "username" parameter will be passed.')),
cfg.BoolOpt('keepalived_use_no_track',
default=True,
help=_('If keepalived without support for "no_track" option '
'is used, this should be set to False. '
'Support for this option was introduced in keepalived '
'2.x'))
] ]
OPTS += config.EXT_NET_BRIDGE_OPTS OPTS += config.EXT_NET_BRIDGE_OPTS

View File

@ -36,6 +36,7 @@ from neutron.agent.linux import keepalived
from neutron.common import constants as n_const from neutron.common import constants as n_const
from neutron.common import utils as common_utils from neutron.common import utils as common_utils
from neutron.conf.agent import common as agent_config from neutron.conf.agent import common as agent_config
from neutron.conf.agent.l3 import config as l3_config
from neutron.conf import common as common_config from neutron.conf import common as common_config
from neutron.tests.common import l3_test_common from neutron.tests.common import l3_test_common
from neutron.tests.common import net_helpers from neutron.tests.common import net_helpers
@ -93,6 +94,7 @@ class L3AgentTestFramework(base.BaseSudoTestCase):
self.mock_plugin_api = mock.patch( self.mock_plugin_api = mock.patch(
'neutron.agent.l3.agent.L3PluginApi').start().return_value 'neutron.agent.l3.agent.L3PluginApi').start().return_value
mock.patch('neutron.agent.rpc.PluginReportStateAPI').start() mock.patch('neutron.agent.rpc.PluginReportStateAPI').start()
l3_config.register_l3_agent_config_opts(l3_config.OPTS, cfg.CONF)
self.conf = self._configure_agent('agent1') self.conf = self._configure_agent('agent1')
self.agent = neutron_l3_agent.L3NATAgentWithStateReport('agent1', self.agent = neutron_l3_agent.L3NATAgentWithStateReport('agent1',
self.conf) self.conf)

View File

@ -20,6 +20,7 @@ from neutron.agent.linux import external_process
from neutron.agent.linux import keepalived from neutron.agent.linux import keepalived
from neutron.agent.linux import utils from neutron.agent.linux import utils
from neutron.common import utils as common_utils from neutron.common import utils as common_utils
from neutron.conf.agent.l3 import config as l3_config
from neutron.tests.functional.agent.linux import helpers from neutron.tests.functional.agent.linux import helpers
from neutron.tests.functional import base from neutron.tests.functional import base
from neutron.tests.unit.agent.linux import test_keepalived from neutron.tests.unit.agent.linux import test_keepalived
@ -30,6 +31,7 @@ class KeepalivedManagerTestCase(base.BaseLoggingTestCase,
def setUp(self): def setUp(self):
super(KeepalivedManagerTestCase, self).setUp() super(KeepalivedManagerTestCase, self).setUp()
l3_config.register_l3_agent_config_opts(l3_config.OPTS, cfg.CONF)
cfg.CONF.set_override('check_child_processes_interval', 1, 'AGENT') cfg.CONF.set_override('check_child_processes_interval', 1, 'AGENT')
self.expected_config = self._get_config() self.expected_config = self._get_config()

View File

@ -18,9 +18,11 @@ import textwrap
import mock import mock
from neutron_lib import constants as n_consts from neutron_lib import constants as n_consts
from oslo_config import cfg
import testtools import testtools
from neutron.agent.linux import keepalived from neutron.agent.linux import keepalived
from neutron.conf.agent.l3 import config as l3_config
from neutron.tests import base from neutron.tests import base
# Keepalived user guide: # Keepalived user guide:
@ -37,7 +39,14 @@ VRRP_ID = 1
VRRP_INTERVAL = 5 VRRP_INTERVAL = 5
class KeepalivedGetFreeRangeTestCase(base.BaseTestCase): class KeepalivedBaseTestCase(base.BaseTestCase):
def setUp(self):
super(KeepalivedBaseTestCase, self).setUp()
l3_config.register_l3_agent_config_opts(l3_config.OPTS, cfg.CONF)
class KeepalivedGetFreeRangeTestCase(KeepalivedBaseTestCase):
def test_get_free_range(self): def test_get_free_range(self):
free_range = keepalived.get_free_range( free_range = keepalived.get_free_range(
parent_range='169.254.0.0/16', parent_range='169.254.0.0/16',
@ -122,7 +131,7 @@ class KeepalivedConfBaseMixin(object):
return config return config
class KeepalivedConfTestCase(base.BaseTestCase, class KeepalivedConfTestCase(KeepalivedBaseTestCase,
KeepalivedConfBaseMixin): KeepalivedConfBaseMixin):
expected = KEEPALIVED_GLOBAL_CONFIG + textwrap.dedent(""" expected = KEEPALIVED_GLOBAL_CONFIG + textwrap.dedent("""
@ -191,7 +200,62 @@ class KeepalivedConfTestCase(base.BaseTestCase,
self.assertEqual(['192.168.2.0/24', '192.168.3.0/24'], current_vips) self.assertEqual(['192.168.2.0/24', '192.168.3.0/24'], current_vips)
class KeepalivedStateExceptionTestCase(base.BaseTestCase): class KeepalivedConfWithoutNoTrackTestCase(KeepalivedConfTestCase):
expected = KEEPALIVED_GLOBAL_CONFIG + textwrap.dedent("""
vrrp_instance VR_1 {
state MASTER
interface eth0
virtual_router_id 1
priority 50
garp_master_delay 60
advert_int 5
authentication {
auth_type AH
auth_pass pass123
}
track_interface {
eth0
}
virtual_ipaddress {
169.254.0.1/24 dev eth0
}
virtual_ipaddress_excluded {
192.168.1.0/24 dev eth1
192.168.2.0/24 dev eth2
192.168.3.0/24 dev eth2
192.168.55.0/24 dev eth10
}
virtual_routes {
0.0.0.0/0 via 192.168.1.1 dev eth1
}
}
vrrp_instance VR_2 {
state MASTER
interface eth4
virtual_router_id 2
priority 50
garp_master_delay 60
mcast_src_ip 224.0.0.1
track_interface {
eth4
}
virtual_ipaddress {
169.254.0.2/24 dev eth4
}
virtual_ipaddress_excluded {
192.168.2.0/24 dev eth2
192.168.3.0/24 dev eth6
192.168.55.0/24 dev eth10
}
}""")
def setUp(self):
super(KeepalivedConfWithoutNoTrackTestCase, self).setUp()
cfg.CONF.set_override('keepalived_use_no_track', False)
class KeepalivedStateExceptionTestCase(KeepalivedBaseTestCase):
def test_state_exception(self): def test_state_exception(self):
invalid_vrrp_state = 'a seal walks' invalid_vrrp_state = 'a seal walks'
self.assertRaises(keepalived.InvalidInstanceStateException, self.assertRaises(keepalived.InvalidInstanceStateException,
@ -207,7 +271,7 @@ class KeepalivedStateExceptionTestCase(base.BaseTestCase):
invalid_auth_type, 'some_password') invalid_auth_type, 'some_password')
class KeepalivedInstanceRoutesTestCase(base.BaseTestCase): class KeepalivedInstanceRoutesTestCase(KeepalivedBaseTestCase):
@classmethod @classmethod
def _get_instance_routes(cls): def _get_instance_routes(cls):
routes = keepalived.KeepalivedInstanceRoutes() routes = keepalived.KeepalivedInstanceRoutes()
@ -248,15 +312,27 @@ class KeepalivedInstanceRoutesTestCase(base.BaseTestCase):
routes = self._get_instance_routes() routes = self._get_instance_routes()
self.assertEqual(expected, '\n'.join(routes.build_config())) self.assertEqual(expected, '\n'.join(routes.build_config()))
def test_build_config_without_no_track_option(self):
expected = """ virtual_routes {
0.0.0.0/0 via 1.0.0.254 dev eth0
::/0 via fe80::3e97:eff:fe26:3bfa/64 dev eth1
10.0.0.0/8 via 1.0.0.1
20.0.0.0/8 via 2.0.0.2
30.0.0.0/8 dev eth0 scope link
}"""
cfg.CONF.set_override('keepalived_use_no_track', False)
routes = self._get_instance_routes()
self.assertEqual(expected, '\n'.join(routes.build_config()))
class KeepalivedInstanceTestCase(base.BaseTestCase,
class KeepalivedInstanceTestCase(KeepalivedBaseTestCase,
KeepalivedConfBaseMixin): KeepalivedConfBaseMixin):
def test_get_primary_vip(self): def test_get_primary_vip(self):
instance = keepalived.KeepalivedInstance('MASTER', 'ha0', 42, instance = keepalived.KeepalivedInstance('MASTER', 'ha0', 42,
['169.254.192.0/18']) ['169.254.192.0/18'])
self.assertEqual('169.254.0.42/24', instance.get_primary_vip()) self.assertEqual('169.254.0.42/24', instance.get_primary_vip())
def test_remove_addresses_by_interface(self): def _test_remove_addresses_by_interface(self, no_track_value):
config = self._get_config() config = self._get_config()
instance = config.get_instance(1) instance = config.get_instance(1)
instance.remove_vips_vroutes_by_interface('eth2') instance.remove_vips_vroutes_by_interface('eth2')
@ -281,10 +357,10 @@ class KeepalivedInstanceTestCase(base.BaseTestCase,
169.254.0.1/24 dev eth0 169.254.0.1/24 dev eth0
} }
virtual_ipaddress_excluded { virtual_ipaddress_excluded {
192.168.1.0/24 dev eth1 no_track 192.168.1.0/24 dev eth1%(no_track)s
} }
virtual_routes { virtual_routes {
0.0.0.0/0 via 192.168.1.1 dev eth1 no_track 0.0.0.0/0 via 192.168.1.1 dev eth1%(no_track)s
} }
} }
vrrp_instance VR_2 { vrrp_instance VR_2 {
@ -301,14 +377,21 @@ class KeepalivedInstanceTestCase(base.BaseTestCase,
169.254.0.2/24 dev eth4 169.254.0.2/24 dev eth4
} }
virtual_ipaddress_excluded { virtual_ipaddress_excluded {
192.168.2.0/24 dev eth2 no_track 192.168.2.0/24 dev eth2%(no_track)s
192.168.3.0/24 dev eth6 no_track 192.168.3.0/24 dev eth6%(no_track)s
192.168.55.0/24 dev eth10 no_track 192.168.55.0/24 dev eth10%(no_track)s
} }
}""") }""" % {'no_track': no_track_value})
self.assertEqual(expected, config.get_config_str()) self.assertEqual(expected, config.get_config_str())
def test_remove_addresses_by_interface(self):
self._test_remove_addresses_by_interface(" no_track")
def test_remove_addresses_by_interface_without_no_track(self):
cfg.CONF.set_override('keepalived_use_no_track', False)
self._test_remove_addresses_by_interface("")
def test_build_config_no_vips(self): def test_build_config_no_vips(self):
expected = textwrap.dedent("""\ expected = textwrap.dedent("""\
vrrp_instance VR_1 { vrrp_instance VR_1 {
@ -351,7 +434,7 @@ vrrp_instance VR_1 {
self.assertEqual(expected, '\n'.join(instance.build_config())) self.assertEqual(expected, '\n'.join(instance.build_config()))
class KeepalivedVipAddressTestCase(base.BaseTestCase): class KeepalivedVipAddressTestCase(KeepalivedBaseTestCase):
def test_vip_with_scope(self): def test_vip_with_scope(self):
vip = keepalived.KeepalivedVipAddress('fe80::3e97:eff:fe26:3bfa/64', vip = keepalived.KeepalivedVipAddress('fe80::3e97:eff:fe26:3bfa/64',
'eth1', 'eth1',
@ -367,20 +450,32 @@ class KeepalivedVipAddressTestCase(base.BaseTestCase):
self.assertEqual(1, len(instance.vips)) self.assertEqual(1, len(instance.vips))
class KeepalivedVirtualRouteTestCase(base.BaseTestCase): class KeepalivedVirtualRouteTestCase(KeepalivedBaseTestCase):
def test_virtual_route_with_dev(self): def test_virtual_route_with_dev(self):
route = keepalived.KeepalivedVirtualRoute(n_consts.IPv4_ANY, '1.2.3.4', route = keepalived.KeepalivedVirtualRoute(n_consts.IPv4_ANY, '1.2.3.4',
'eth0') 'eth0')
self.assertEqual('0.0.0.0/0 via 1.2.3.4 dev eth0 no_track', self.assertEqual('0.0.0.0/0 via 1.2.3.4 dev eth0 no_track',
route.build_config()) route.build_config())
def test_virtual_route_with_dev_without_no_track(self):
cfg.CONF.set_override('keepalived_use_no_track', False)
route = keepalived.KeepalivedVirtualRoute(n_consts.IPv4_ANY, '1.2.3.4',
'eth0')
self.assertEqual('0.0.0.0/0 via 1.2.3.4 dev eth0',
route.build_config())
def test_virtual_route_without_dev(self): def test_virtual_route_without_dev(self):
route = keepalived.KeepalivedVirtualRoute('50.0.0.0/8', '1.2.3.4') route = keepalived.KeepalivedVirtualRoute('50.0.0.0/8', '1.2.3.4')
self.assertEqual('50.0.0.0/8 via 1.2.3.4 no_track', self.assertEqual('50.0.0.0/8 via 1.2.3.4 no_track',
route.build_config()) route.build_config())
def test_virtual_route_without_dev_without_no_track(self):
cfg.CONF.set_override('keepalived_use_no_track', False)
route = keepalived.KeepalivedVirtualRoute('50.0.0.0/8', '1.2.3.4')
self.assertEqual('50.0.0.0/8 via 1.2.3.4', route.build_config())
class KeepalivedTrackScriptTestCase(base.BaseTestCase):
class KeepalivedTrackScriptTestCase(KeepalivedBaseTestCase):
def test_build_config_preamble(self): def test_build_config_preamble(self):
exp_conf = [ exp_conf = [

View File

@ -0,0 +1,7 @@
---
features:
- |
New config option ``keepalived_use_no_track`` was added. If keepalived
version used on the deployment does not support ``no_track`` flag in its
config file (e.g. keepalived 1.x), this option should be set to ``False``.
Default value of this option is ``True``.