Merge "[L3 HA] Add "no_track" option to VIPs in keepalived config" into stable/rocky

This commit is contained in:
Zuul 2020-04-24 18:22:19 +00:00 committed by Gerrit Code Review
commit cb2677ff70
3 changed files with 71 additions and 63 deletions

View File

@ -85,24 +85,28 @@ class InvalidAuthenticationTypeException(exceptions.NeutronException):
class KeepalivedVipAddress(object): class KeepalivedVipAddress(object):
"""A virtual address entry of a keepalived configuration.""" """A virtual address entry of a keepalived configuration."""
def __init__(self, ip_address, interface_name, scope=None): def __init__(self, ip_address, interface_name, scope=None, track=True):
self.ip_address = ip_address self.ip_address = ip_address
self.interface_name = interface_name self.interface_name = interface_name
self.scope = scope self.scope = scope
self.track = track
def __eq__(self, other): def __eq__(self, other):
return (isinstance(other, KeepalivedVipAddress) and return (isinstance(other, KeepalivedVipAddress) and
self.ip_address == other.ip_address) self.ip_address == other.ip_address)
def __str__(self): def __str__(self):
return '[%s, %s, %s]' % (self.ip_address, return '[%s, %s, %s, %s]' % (self.ip_address,
self.interface_name, self.interface_name,
self.scope) self.scope,
self.track)
def build_config(self): def build_config(self):
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:
result += ' no_track'
return result return result
@ -124,6 +128,7 @@ 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'
return output return output
@ -200,7 +205,8 @@ class KeepalivedInstance(object):
self.authentication = (auth_type, password) self.authentication = (auth_type, password)
def add_vip(self, ip_cidr, interface_name, scope): def add_vip(self, ip_cidr, interface_name, scope):
vip = KeepalivedVipAddress(ip_cidr, interface_name, scope) track = interface_name in self.track_interfaces
vip = KeepalivedVipAddress(ip_cidr, interface_name, scope, track=track)
if vip not in self.vips: if vip not in self.vips:
self.vips.append(vip) self.vips.append(vip)
else: else:

View File

@ -15,7 +15,6 @@
import copy import copy
import functools import functools
import textwrap
import mock import mock
import netaddr import netaddr
@ -47,6 +46,39 @@ _uuid = uuidutils.generate_uuid
OVS_INTERFACE_DRIVER = 'neutron.agent.linux.interface.OVSInterfaceDriver' OVS_INTERFACE_DRIVER = 'neutron.agent.linux.interface.OVSInterfaceDriver'
KEEPALIVED_CONFIG = """\
global_defs {
notification_email_from %(email_from)s
router_id %(router_id)s
}
vrrp_instance VR_1 {
state BACKUP
interface %(ha_device_name)s
virtual_router_id 1
priority 50
garp_master_delay 60
nopreempt
advert_int 2
track_interface {
%(ha_device_name)s
}
virtual_ipaddress {
169.254.0.1/24 dev %(ha_device_name)s
}
virtual_ipaddress_excluded {
%(floating_ip_cidr)s dev %(ex_device_name)s no_track
%(external_device_cidr)s dev %(ex_device_name)s no_track
%(internal_device_cidr)s dev %(internal_device_name)s no_track
%(ex_port_ipv6)s dev %(ex_device_name)s scope link no_track
%(int_port_ipv6)s dev %(internal_device_name)s scope link no_track
}
virtual_routes {
0.0.0.0/0 via %(default_gateway_ip)s dev %(ex_device_name)s no_track
8.8.8.0/24 via 19.4.4.4 no_track
%(extra_subnet_cidr)s dev %(ex_device_name)s scope link no_track
}
}"""
def get_ovs_bridge(br_name): def get_ovs_bridge(br_name):
return ovs_lib.OVSBridge(br_name) return ovs_lib.OVSBridge(br_name)
@ -432,38 +464,7 @@ class L3AgentTestFramework(base.BaseSudoTestCase):
router.get_floating_ips()[0]['floating_ip_address']) router.get_floating_ips()[0]['floating_ip_address'])
default_gateway_ip = external_port['subnets'][0].get('gateway_ip') default_gateway_ip = external_port['subnets'][0].get('gateway_ip')
extra_subnet_cidr = external_port['extra_subnets'][0].get('cidr') extra_subnet_cidr = external_port['extra_subnets'][0].get('cidr')
return textwrap.dedent("""\ return KEEPALIVED_CONFIG % {
global_defs {
notification_email_from %(email_from)s
router_id %(router_id)s
}
vrrp_instance VR_1 {
state BACKUP
interface %(ha_device_name)s
virtual_router_id 1
priority 50
garp_master_delay 60
nopreempt
advert_int 2
track_interface {
%(ha_device_name)s
}
virtual_ipaddress {
169.254.0.1/24 dev %(ha_device_name)s
}
virtual_ipaddress_excluded {
%(floating_ip_cidr)s dev %(ex_device_name)s
%(external_device_cidr)s dev %(ex_device_name)s
%(internal_device_cidr)s dev %(internal_device_name)s
%(ex_port_ipv6)s dev %(ex_device_name)s scope link
%(int_port_ipv6)s dev %(internal_device_name)s scope link
}
virtual_routes {
0.0.0.0/0 via %(default_gateway_ip)s dev %(ex_device_name)s
8.8.8.0/24 via 19.4.4.4
%(extra_subnet_cidr)s dev %(ex_device_name)s scope link
}
}""") % {
'email_from': keepalived.KEEPALIVED_EMAIL_FROM, 'email_from': keepalived.KEEPALIVED_EMAIL_FROM,
'router_id': keepalived.KEEPALIVED_ROUTER_ID, 'router_id': keepalived.KEEPALIVED_ROUTER_ID,
'ha_device_name': ha_device_name, 'ha_device_name': ha_device_name,

View File

@ -83,16 +83,16 @@ class KeepalivedConfBaseMixin(object):
instance1.track_interfaces.append("eth0") instance1.track_interfaces.append("eth0")
vip_address1 = keepalived.KeepalivedVipAddress('192.168.1.0/24', vip_address1 = keepalived.KeepalivedVipAddress('192.168.1.0/24',
'eth1') 'eth1', track=False)
vip_address2 = keepalived.KeepalivedVipAddress('192.168.2.0/24', vip_address2 = keepalived.KeepalivedVipAddress('192.168.2.0/24',
'eth2') 'eth2', track=False)
vip_address3 = keepalived.KeepalivedVipAddress('192.168.3.0/24', vip_address3 = keepalived.KeepalivedVipAddress('192.168.3.0/24',
'eth2') 'eth2', track=False)
vip_address_ex = keepalived.KeepalivedVipAddress('192.168.55.0/24', vip_address_ex = keepalived.KeepalivedVipAddress('192.168.55.0/24',
'eth10') 'eth10', track=False)
instance1.vips.append(vip_address1) instance1.vips.append(vip_address1)
instance1.vips.append(vip_address2) instance1.vips.append(vip_address2)
@ -110,7 +110,7 @@ class KeepalivedConfBaseMixin(object):
instance2.track_interfaces.append("eth4") instance2.track_interfaces.append("eth4")
vip_address1 = keepalived.KeepalivedVipAddress('192.168.3.0/24', vip_address1 = keepalived.KeepalivedVipAddress('192.168.3.0/24',
'eth6') 'eth6', track=False)
instance2.vips.append(vip_address1) instance2.vips.append(vip_address1)
instance2.vips.append(vip_address2) instance2.vips.append(vip_address2)
@ -144,13 +144,13 @@ class KeepalivedConfTestCase(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 192.168.1.0/24 dev eth1 no_track
192.168.2.0/24 dev eth2 192.168.2.0/24 dev eth2 no_track
192.168.3.0/24 dev eth2 192.168.3.0/24 dev eth2 no_track
192.168.55.0/24 dev eth10 192.168.55.0/24 dev eth10 no_track
} }
virtual_routes { virtual_routes {
0.0.0.0/0 via 192.168.1.1 dev eth1 0.0.0.0/0 via 192.168.1.1 dev eth1 no_track
} }
} }
vrrp_instance VR_2 { vrrp_instance VR_2 {
@ -167,9 +167,9 @@ class KeepalivedConfTestCase(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 192.168.2.0/24 dev eth2 no_track
192.168.3.0/24 dev eth6 192.168.3.0/24 dev eth6 no_track
192.168.55.0/24 dev eth10 192.168.55.0/24 dev eth10 no_track
} }
}""") }""")
@ -239,11 +239,11 @@ class KeepalivedInstanceRoutesTestCase(base.BaseTestCase):
def test_build_config(self): def test_build_config(self):
expected = """ virtual_routes { expected = """ virtual_routes {
0.0.0.0/0 via 1.0.0.254 dev eth0 0.0.0.0/0 via 1.0.0.254 dev eth0 no_track
::/0 via fe80::3e97:eff:fe26:3bfa/64 dev eth1 ::/0 via fe80::3e97:eff:fe26:3bfa/64 dev eth1 no_track
10.0.0.0/8 via 1.0.0.1 10.0.0.0/8 via 1.0.0.1 no_track
20.0.0.0/8 via 2.0.0.2 20.0.0.0/8 via 2.0.0.2 no_track
30.0.0.0/8 dev eth0 scope link 30.0.0.0/8 dev eth0 scope link no_track
}""" }"""
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()))
@ -281,10 +281,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 192.168.1.0/24 dev eth1 no_track
} }
virtual_routes { virtual_routes {
0.0.0.0/0 via 192.168.1.1 dev eth1 0.0.0.0/0 via 192.168.1.1 dev eth1 no_track
} }
} }
vrrp_instance VR_2 { vrrp_instance VR_2 {
@ -301,9 +301,9 @@ 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 192.168.2.0/24 dev eth2 no_track
192.168.3.0/24 dev eth6 192.168.3.0/24 dev eth6 no_track
192.168.55.0/24 dev eth10 192.168.55.0/24 dev eth10 no_track
} }
}""") }""")
@ -371,12 +371,13 @@ class KeepalivedVirtualRouteTestCase(base.BaseTestCase):
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', 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_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', route.build_config()) self.assertEqual('50.0.0.0/8 via 1.2.3.4 no_track',
route.build_config())
class KeepalivedTrackScriptTestCase(base.BaseTestCase): class KeepalivedTrackScriptTestCase(base.BaseTestCase):