Merge "Preserve link local IP allocations for DVR fip ns across restart"
This commit is contained in:
commit
f9981d0495
|
@ -20,6 +20,7 @@ import eventlet
|
||||||
eventlet.monkey_patch()
|
eventlet.monkey_patch()
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
import os
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
import Queue
|
import Queue
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ SNAT_NS_PREFIX = 'snat-'
|
||||||
FIP_2_ROUTER_DEV_PREFIX = 'fpr-'
|
FIP_2_ROUTER_DEV_PREFIX = 'fpr-'
|
||||||
ROUTER_2_FIP_DEV_PREFIX = 'rfp-'
|
ROUTER_2_FIP_DEV_PREFIX = 'rfp-'
|
||||||
FIP_EXT_DEV_PREFIX = 'fg-'
|
FIP_EXT_DEV_PREFIX = 'fg-'
|
||||||
FIP_LL_PREFIX = '169.254.30.'
|
FIP_LL_SUBNET = '169.254.30.0/23'
|
||||||
# Route Table index for FIPs
|
# Route Table index for FIPs
|
||||||
FIP_RT_TBL = 16
|
FIP_RT_TBL = 16
|
||||||
# Rule priority range for FIPs
|
# Rule priority range for FIPs
|
||||||
|
@ -142,6 +143,99 @@ class L3PluginApi(n_rpc.RpcProxy):
|
||||||
version='1.3')
|
version='1.3')
|
||||||
|
|
||||||
|
|
||||||
|
class LinkLocalAddressPair(netaddr.IPNetwork):
|
||||||
|
def __init__(self, addr):
|
||||||
|
super(LinkLocalAddressPair, self).__init__(addr)
|
||||||
|
|
||||||
|
def get_pair(self):
|
||||||
|
"""Builds an address pair from the first and last addresses. """
|
||||||
|
return (netaddr.IPNetwork("%s/%s" % (self.network, self.prefixlen)),
|
||||||
|
netaddr.IPNetwork("%s/%s" % (self.broadcast, self.prefixlen)))
|
||||||
|
|
||||||
|
|
||||||
|
class LinkLocalAllocator(object):
|
||||||
|
"""Manages allocation of link local IP addresses.
|
||||||
|
|
||||||
|
These link local addresses are used for routing inside the fip namespaces.
|
||||||
|
The associations need to persist across agent restarts to maintain
|
||||||
|
consistency. Without this, there is disruption in network connectivity
|
||||||
|
as the agent rewires the connections with the new IP address assocations.
|
||||||
|
|
||||||
|
Persisting these in the database is unnecessary and would degrade
|
||||||
|
performance.
|
||||||
|
"""
|
||||||
|
def __init__(self, state_file, subnet):
|
||||||
|
"""Read the file with previous allocations recorded.
|
||||||
|
|
||||||
|
See the note in the allocate method for more detail.
|
||||||
|
"""
|
||||||
|
self.state_file = state_file
|
||||||
|
subnet = netaddr.IPNetwork(subnet)
|
||||||
|
|
||||||
|
self.allocations = {}
|
||||||
|
|
||||||
|
self.remembered = {}
|
||||||
|
for line in self._read():
|
||||||
|
key, cidr = line.strip().split(',')
|
||||||
|
self.remembered[key] = LinkLocalAddressPair(cidr)
|
||||||
|
|
||||||
|
self.pool = set(LinkLocalAddressPair(s) for s in subnet.subnet(31))
|
||||||
|
self.pool.difference_update(self.remembered.values())
|
||||||
|
|
||||||
|
def allocate(self, key):
|
||||||
|
"""Try to allocate a link local address pair.
|
||||||
|
|
||||||
|
I expect this to work in all cases because I expect the pool size to be
|
||||||
|
large enough for any situation. Nonetheless, there is some defensive
|
||||||
|
programming in here.
|
||||||
|
|
||||||
|
Since the allocations are persisted, there is the chance to leak
|
||||||
|
allocations which should have been released but were not. This leak
|
||||||
|
could eventually exhaust the pool.
|
||||||
|
|
||||||
|
So, if a new allocation is needed, the code first checks to see if
|
||||||
|
there are any remembered allocations for the key. If not, it checks
|
||||||
|
the free pool. If the free pool is empty then it dumps the remembered
|
||||||
|
allocations to free the pool. This final desparate step will not
|
||||||
|
happen often in practice.
|
||||||
|
"""
|
||||||
|
if key in self.remembered:
|
||||||
|
self.allocations[key] = self.remembered.pop(key)
|
||||||
|
return self.allocations[key]
|
||||||
|
|
||||||
|
if not self.pool:
|
||||||
|
# Desparate times. Try to get more in the pool.
|
||||||
|
self.pool.update(self.remembered.values())
|
||||||
|
self.remembered.clear()
|
||||||
|
if not self.pool:
|
||||||
|
# More than 256 routers on a compute node!
|
||||||
|
raise RuntimeError(_("Cannot allocate link local address"))
|
||||||
|
|
||||||
|
self.allocations[key] = self.pool.pop()
|
||||||
|
self._write_allocations()
|
||||||
|
return self.allocations[key]
|
||||||
|
|
||||||
|
def release(self, key):
|
||||||
|
self.pool.add(self.allocations.pop(key))
|
||||||
|
self._write_allocations()
|
||||||
|
|
||||||
|
def _write_allocations(self):
|
||||||
|
current = ["%s,%s\n" % (k, v) for k, v in self.allocations.items()]
|
||||||
|
remembered = ["%s,%s\n" % (k, v) for k, v in self.remembered.items()]
|
||||||
|
current.extend(remembered)
|
||||||
|
self._write(current)
|
||||||
|
|
||||||
|
def _write(self, lines):
|
||||||
|
with open(self.state_file, "w") as f:
|
||||||
|
f.writelines(lines)
|
||||||
|
|
||||||
|
def _read(self):
|
||||||
|
if not os.path.exists(self.state_file):
|
||||||
|
return []
|
||||||
|
with open(self.state_file) as f:
|
||||||
|
return f.readlines()
|
||||||
|
|
||||||
|
|
||||||
class RouterInfo(object):
|
class RouterInfo(object):
|
||||||
|
|
||||||
def __init__(self, router_id, root_helper, use_namespaces, router):
|
def __init__(self, router_id, root_helper, use_namespaces, router):
|
||||||
|
@ -164,10 +258,8 @@ class RouterInfo(object):
|
||||||
namespace=self.ns_name)
|
namespace=self.ns_name)
|
||||||
self.routes = []
|
self.routes = []
|
||||||
# DVR Data
|
# DVR Data
|
||||||
# Linklocal router to floating IP addr
|
# Linklocal subnet for router and floating IP namespace link
|
||||||
self.rtr_2_fip = None
|
self.rtr_fip_subnet = None
|
||||||
# Linklocal floating to router IP addr
|
|
||||||
self.fip_2_rtr = None
|
|
||||||
self.dist_fip_count = 0
|
self.dist_fip_count = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -433,7 +525,9 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
|
||||||
# dvr data
|
# dvr data
|
||||||
self.agent_gateway_port = None
|
self.agent_gateway_port = None
|
||||||
self.agent_fip_count = 0
|
self.agent_fip_count = 0
|
||||||
self.local_ips = set(range(2, 251))
|
self.local_subnets = LinkLocalAllocator(
|
||||||
|
os.path.join(self.conf.state_path, 'fip-linklocal-networks'),
|
||||||
|
FIP_LL_SUBNET)
|
||||||
self.fip_priorities = set(range(FIP_PR_START, FIP_PR_END))
|
self.fip_priorities = set(range(FIP_PR_START, FIP_PR_END))
|
||||||
|
|
||||||
self._queue = RouterProcessingQueue()
|
self._queue = RouterProcessingQueue()
|
||||||
|
@ -1374,24 +1468,23 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
|
||||||
fip_ns_name = self.get_fip_ns_name(str(network_id))
|
fip_ns_name = self.get_fip_ns_name(str(network_id))
|
||||||
|
|
||||||
# add link local IP to interface
|
# add link local IP to interface
|
||||||
if ri.rtr_2_fip is None:
|
if ri.rtr_fip_subnet is None:
|
||||||
ri.rtr_2_fip = FIP_LL_PREFIX + str(self.local_ips.pop())
|
ri.rtr_fip_subnet = self.local_subnets.allocate(ri.router_id)
|
||||||
if ri.fip_2_rtr is None:
|
rtr_2_fip, fip_2_rtr = ri.rtr_fip_subnet.get_pair()
|
||||||
ri.fip_2_rtr = FIP_LL_PREFIX + str(self.local_ips.pop())
|
|
||||||
ip_wrapper = ip_lib.IPWrapper(self.root_helper,
|
ip_wrapper = ip_lib.IPWrapper(self.root_helper,
|
||||||
namespace=ri.ns_name)
|
namespace=ri.ns_name)
|
||||||
int_dev = ip_wrapper.add_veth(rtr_2_fip_name,
|
int_dev = ip_wrapper.add_veth(rtr_2_fip_name,
|
||||||
fip_2_rtr_name, fip_ns_name)
|
fip_2_rtr_name, fip_ns_name)
|
||||||
self.internal_ns_interface_added(ri.rtr_2_fip + '/31',
|
self.internal_ns_interface_added(str(rtr_2_fip),
|
||||||
rtr_2_fip_name, ri.ns_name)
|
rtr_2_fip_name, ri.ns_name)
|
||||||
self.internal_ns_interface_added(ri.fip_2_rtr + '/31',
|
self.internal_ns_interface_added(str(fip_2_rtr),
|
||||||
fip_2_rtr_name, fip_ns_name)
|
fip_2_rtr_name, fip_ns_name)
|
||||||
int_dev[0].link.set_up()
|
int_dev[0].link.set_up()
|
||||||
int_dev[1].link.set_up()
|
int_dev[1].link.set_up()
|
||||||
# add default route for the link local interface
|
# add default route for the link local interface
|
||||||
device = ip_lib.IPDevice(rtr_2_fip_name, self.root_helper,
|
device = ip_lib.IPDevice(rtr_2_fip_name, self.root_helper,
|
||||||
namespace=ri.ns_name)
|
namespace=ri.ns_name)
|
||||||
device.route.add_gateway(ri.fip_2_rtr, table=FIP_RT_TBL)
|
device.route.add_gateway(str(fip_2_rtr.ip), table=FIP_RT_TBL)
|
||||||
#setup the NAT rules and chains
|
#setup the NAT rules and chains
|
||||||
self._handle_router_fip_nat_rules(ri, rtr_2_fip_name, 'add_rules')
|
self._handle_router_fip_nat_rules(ri, rtr_2_fip_name, 'add_rules')
|
||||||
|
|
||||||
|
@ -1408,9 +1501,10 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
|
||||||
#Add routing rule in fip namespace
|
#Add routing rule in fip namespace
|
||||||
fip_cidr = str(floating_ip) + FLOATING_IP_CIDR_SUFFIX
|
fip_cidr = str(floating_ip) + FLOATING_IP_CIDR_SUFFIX
|
||||||
fip_ns_name = self.get_fip_ns_name(str(fip['floating_network_id']))
|
fip_ns_name = self.get_fip_ns_name(str(fip['floating_network_id']))
|
||||||
|
rtr_2_fip, _ = ri.rtr_fip_subnet.get_pair()
|
||||||
device = ip_lib.IPDevice(fip_2_rtr_name, self.root_helper,
|
device = ip_lib.IPDevice(fip_2_rtr_name, self.root_helper,
|
||||||
namespace=fip_ns_name)
|
namespace=fip_ns_name)
|
||||||
device.route.add_route(fip_cidr, ri.rtr_2_fip)
|
device.route.add_route(fip_cidr, str(rtr_2_fip.ip))
|
||||||
interface_name = (
|
interface_name = (
|
||||||
self.get_fip_ext_device_name(self.agent_gateway_port['id']))
|
self.get_fip_ext_device_name(self.agent_gateway_port['id']))
|
||||||
self._send_gratuitous_arp_packet(fip_ns_name,
|
self._send_gratuitous_arp_packet(fip_ns_name,
|
||||||
|
@ -1425,6 +1519,7 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
|
||||||
floating_ip = fip_cidr.split('/')[0]
|
floating_ip = fip_cidr.split('/')[0]
|
||||||
rtr_2_fip_name = self.get_rtr_int_device_name(ri.router_id)
|
rtr_2_fip_name = self.get_rtr_int_device_name(ri.router_id)
|
||||||
fip_2_rtr_name = self.get_fip_int_device_name(ri.router_id)
|
fip_2_rtr_name = self.get_fip_int_device_name(ri.router_id)
|
||||||
|
rtr_2_fip, fip_2_rtr = ri.rtr_fip_subnet.get_pair()
|
||||||
fip_ns_name = self.get_fip_ns_name(str(self._fetch_external_net_id()))
|
fip_ns_name = self.get_fip_ns_name(str(self._fetch_external_net_id()))
|
||||||
ip_rule_rtr = ip_lib.IpRule(self.root_helper, namespace=ri.ns_name)
|
ip_rule_rtr = ip_lib.IpRule(self.root_helper, namespace=ri.ns_name)
|
||||||
if floating_ip in ri.floating_ips_dict:
|
if floating_ip in ri.floating_ips_dict:
|
||||||
|
@ -1438,7 +1533,7 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
|
||||||
device = ip_lib.IPDevice(fip_2_rtr_name, self.root_helper,
|
device = ip_lib.IPDevice(fip_2_rtr_name, self.root_helper,
|
||||||
namespace=fip_ns_name)
|
namespace=fip_ns_name)
|
||||||
|
|
||||||
device.route.delete_route(fip_cidr, ri.rtr_2_fip)
|
device.route.delete_route(fip_cidr, str(rtr_2_fip.ip))
|
||||||
# check if this is the last FIP for this router
|
# check if this is the last FIP for this router
|
||||||
ri.dist_fip_count = ri.dist_fip_count - 1
|
ri.dist_fip_count = ri.dist_fip_count - 1
|
||||||
if ri.dist_fip_count == 0:
|
if ri.dist_fip_count == 0:
|
||||||
|
@ -1446,11 +1541,9 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
|
||||||
device = ip_lib.IPDevice(rtr_2_fip_name, self.root_helper,
|
device = ip_lib.IPDevice(rtr_2_fip_name, self.root_helper,
|
||||||
namespace=ri.ns_name)
|
namespace=ri.ns_name)
|
||||||
ns_ip = ip_lib.IPWrapper(self.root_helper, namespace=fip_ns_name)
|
ns_ip = ip_lib.IPWrapper(self.root_helper, namespace=fip_ns_name)
|
||||||
device.route.delete_gateway(ri.fip_2_rtr, table=FIP_RT_TBL)
|
device.route.delete_gateway(str(fip_2_rtr.ip), table=FIP_RT_TBL)
|
||||||
self.local_ips.add(ri.rtr_2_fip.rsplit('.', 1)[1])
|
self.local_subnets.release(ri.router_id)
|
||||||
ri.rtr_2_fip = None
|
ri.rtr_fip_subnet = None
|
||||||
self.local_ips.add(ri.fip_2_rtr.rsplit('.', 1)[1])
|
|
||||||
ri.fip_2_rtr = None
|
|
||||||
ns_ip.del_veth(fip_2_rtr_name)
|
ns_ip.del_veth(fip_2_rtr_name)
|
||||||
# clean up fip-namespace if this is the last FIP
|
# clean up fip-namespace if this is the last FIP
|
||||||
self.agent_fip_count = self.agent_fip_count - 1
|
self.agent_fip_count = self.agent_fip_count - 1
|
||||||
|
|
|
@ -49,6 +49,7 @@ class TestVarmourRouter(base.BaseTestCase):
|
||||||
self.conf.set_override('interface_driver',
|
self.conf.set_override('interface_driver',
|
||||||
'neutron.agent.linux.interface.NullDriver')
|
'neutron.agent.linux.interface.NullDriver')
|
||||||
self.conf.root_helper = 'sudo'
|
self.conf.root_helper = 'sudo'
|
||||||
|
self.conf.state_path = ''
|
||||||
|
|
||||||
self.device_exists_p = mock.patch(
|
self.device_exists_p = mock.patch(
|
||||||
'neutron.agent.linux.ip_lib.device_exists')
|
'neutron.agent.linux.ip_lib.device_exists')
|
||||||
|
|
|
@ -50,6 +50,7 @@ class TestBasicRouterOperations(base.BaseTestCase):
|
||||||
self.conf.set_override('interface_driver',
|
self.conf.set_override('interface_driver',
|
||||||
'neutron.agent.linux.interface.NullDriver')
|
'neutron.agent.linux.interface.NullDriver')
|
||||||
self.conf.root_helper = 'sudo'
|
self.conf.root_helper = 'sudo'
|
||||||
|
self.conf.state_path = ''
|
||||||
|
|
||||||
self.device_exists_p = mock.patch(
|
self.device_exists_p = mock.patch(
|
||||||
'neutron.agent.linux.ip_lib.device_exists')
|
'neutron.agent.linux.ip_lib.device_exists')
|
||||||
|
|
|
@ -118,6 +118,83 @@ class TestExclusiveRouterProcessor(base.BaseTestCase):
|
||||||
self.assertEqual(2, len([i for i in master.updates()]))
|
self.assertEqual(2, len([i for i in master.updates()]))
|
||||||
|
|
||||||
|
|
||||||
|
class TestLinkLocalAddrAllocator(base.BaseTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestLinkLocalAddrAllocator, self).setUp()
|
||||||
|
self.subnet = netaddr.IPNetwork('169.254.31.0/24')
|
||||||
|
|
||||||
|
def test__init__(self):
|
||||||
|
a = l3_agent.LinkLocalAllocator('/file', self.subnet.cidr)
|
||||||
|
self.assertEqual('/file', a.state_file)
|
||||||
|
self.assertEqual({}, a.allocations)
|
||||||
|
|
||||||
|
def test__init__readfile(self):
|
||||||
|
with mock.patch.object(l3_agent.LinkLocalAllocator, '_read') as read:
|
||||||
|
read.return_value = ["da873ca2,169.254.31.28/31\n"]
|
||||||
|
a = l3_agent.LinkLocalAllocator('/file', self.subnet.cidr)
|
||||||
|
|
||||||
|
self.assertTrue('da873ca2' in a.remembered)
|
||||||
|
self.assertEqual({}, a.allocations)
|
||||||
|
|
||||||
|
def test_allocate(self):
|
||||||
|
a = l3_agent.LinkLocalAllocator('/file', self.subnet.cidr)
|
||||||
|
with mock.patch.object(l3_agent.LinkLocalAllocator, '_write') as write:
|
||||||
|
subnet = a.allocate('deadbeef')
|
||||||
|
|
||||||
|
self.assertTrue('deadbeef' in a.allocations)
|
||||||
|
self.assertTrue(subnet not in a.pool)
|
||||||
|
self._check_allocations(a.allocations)
|
||||||
|
write.assert_called_once_with(['deadbeef,%s\n' % subnet.cidr])
|
||||||
|
|
||||||
|
def test_allocate_from_file(self):
|
||||||
|
with mock.patch.object(l3_agent.LinkLocalAllocator, '_read') as read:
|
||||||
|
read.return_value = ["deadbeef,169.254.31.88/31\n"]
|
||||||
|
a = l3_agent.LinkLocalAllocator('/file', self.subnet.cidr)
|
||||||
|
|
||||||
|
with mock.patch.object(l3_agent.LinkLocalAllocator, '_write') as write:
|
||||||
|
subnet = a.allocate('deadbeef')
|
||||||
|
|
||||||
|
self.assertEqual(netaddr.IPNetwork('169.254.31.88/31'), subnet)
|
||||||
|
self.assertTrue(subnet not in a.pool)
|
||||||
|
self._check_allocations(a.allocations)
|
||||||
|
self.assertFalse(write.called)
|
||||||
|
|
||||||
|
def test_allocate_exhausted_pool(self):
|
||||||
|
subnet = netaddr.IPNetwork('169.254.31.0/31')
|
||||||
|
with mock.patch.object(l3_agent.LinkLocalAllocator, '_read') as read:
|
||||||
|
read.return_value = ["deadbeef,169.254.31.0/31\n"]
|
||||||
|
a = l3_agent.LinkLocalAllocator('/file', subnet.cidr)
|
||||||
|
|
||||||
|
with mock.patch.object(l3_agent.LinkLocalAllocator, '_write') as write:
|
||||||
|
allocation = a.allocate('abcdef12')
|
||||||
|
|
||||||
|
self.assertEqual(subnet, allocation)
|
||||||
|
self.assertFalse('deadbeef' in a.allocations)
|
||||||
|
self.assertTrue('abcdef12' in a.allocations)
|
||||||
|
self.assertTrue(allocation not in a.pool)
|
||||||
|
self._check_allocations(a.allocations)
|
||||||
|
write.assert_called_once_with(['abcdef12,%s\n' % allocation.cidr])
|
||||||
|
|
||||||
|
self.assertRaises(RuntimeError, a.allocate, 'deadbeef')
|
||||||
|
|
||||||
|
def test_release(self):
|
||||||
|
with mock.patch.object(l3_agent.LinkLocalAllocator, '_write') as write:
|
||||||
|
a = l3_agent.LinkLocalAllocator('/file', self.subnet.cidr)
|
||||||
|
subnet = a.allocate('deadbeef')
|
||||||
|
write.reset_mock()
|
||||||
|
a.release('deadbeef')
|
||||||
|
|
||||||
|
self.assertTrue('deadbeef' not in a.allocations)
|
||||||
|
self.assertTrue(subnet in a.pool)
|
||||||
|
self.assertEqual({}, a.allocations)
|
||||||
|
write.assert_called_once_with([])
|
||||||
|
|
||||||
|
def _check_allocations(self, allocations):
|
||||||
|
for key, subnet in allocations.items():
|
||||||
|
self.assertTrue(subnet in self.subnet)
|
||||||
|
self.assertEqual(subnet.prefixlen, 31)
|
||||||
|
|
||||||
|
|
||||||
def router_append_interface(router, count=1, ip_version=4, ra_mode=None,
|
def router_append_interface(router, count=1, ip_version=4, ra_mode=None,
|
||||||
addr_mode=None):
|
addr_mode=None):
|
||||||
if ip_version == 4:
|
if ip_version == 4:
|
||||||
|
@ -822,8 +899,9 @@ class TestBasicRouterOperations(base.BaseTestCase):
|
||||||
device.addr.list.return_value = []
|
device.addr.list.return_value = []
|
||||||
ri.iptables_manager.ipv4['nat'] = mock.MagicMock()
|
ri.iptables_manager.ipv4['nat'] = mock.MagicMock()
|
||||||
|
|
||||||
fip_statuses = agent.process_router_floating_ip_addresses(
|
with mock.patch.object(l3_agent.LinkLocalAllocator, '_write'):
|
||||||
ri, {'id': _uuid()})
|
fip_statuses = agent.process_router_floating_ip_addresses(
|
||||||
|
ri, {'id': _uuid()})
|
||||||
self.assertEqual({fip_id: l3_constants.FLOATINGIP_STATUS_ACTIVE},
|
self.assertEqual({fip_id: l3_constants.FLOATINGIP_STATUS_ACTIVE},
|
||||||
fip_statuses)
|
fip_statuses)
|
||||||
device.addr.add.assert_called_once_with(4, '15.1.2.3/32', '15.1.2.3')
|
device.addr.add.assert_called_once_with(4, '15.1.2.3/32', '15.1.2.3')
|
||||||
|
@ -1878,12 +1956,13 @@ class TestBasicRouterOperations(base.BaseTestCase):
|
||||||
fip_2_rtr_name = agent.get_fip_int_device_name(ri.router_id)
|
fip_2_rtr_name = agent.get_fip_int_device_name(ri.router_id)
|
||||||
fip_ns_name = agent.get_fip_ns_name(str(fip['floating_network_id']))
|
fip_ns_name = agent.get_fip_ns_name(str(fip['floating_network_id']))
|
||||||
|
|
||||||
agent.create_rtr_2_fip_link(ri, fip['floating_network_id'])
|
with mock.patch.object(l3_agent.LinkLocalAllocator, '_write'):
|
||||||
|
agent.create_rtr_2_fip_link(ri, fip['floating_network_id'])
|
||||||
self.mock_ip.add_veth.assert_called_with(rtr_2_fip_name,
|
self.mock_ip.add_veth.assert_called_with(rtr_2_fip_name,
|
||||||
fip_2_rtr_name, fip_ns_name)
|
fip_2_rtr_name, fip_ns_name)
|
||||||
# TODO(mrsmith): add more aasserts -
|
# TODO(mrsmith): add more aasserts -
|
||||||
self.mock_ip_dev.route.add_gateway.assert_called_once_with(
|
self.mock_ip_dev.route.add_gateway.assert_called_once_with(
|
||||||
ri.fip_2_rtr, table=16)
|
'169.254.31.29', table=16)
|
||||||
|
|
||||||
# TODO(mrsmith): test _create_agent_gateway_port
|
# TODO(mrsmith): test _create_agent_gateway_port
|
||||||
|
|
||||||
|
@ -1907,12 +1986,14 @@ class TestBasicRouterOperations(base.BaseTestCase):
|
||||||
'floating_network_id': _uuid(),
|
'floating_network_id': _uuid(),
|
||||||
'port_id': _uuid()}
|
'port_id': _uuid()}
|
||||||
agent.agent_gateway_port = agent_gw_port
|
agent.agent_gateway_port = agent_gw_port
|
||||||
|
ri.rtr_fip_subnet = l3_agent.LinkLocalAddressPair('169.254.30.42/31')
|
||||||
agent.floating_ip_added_dist(ri, fip)
|
agent.floating_ip_added_dist(ri, fip)
|
||||||
self.mock_rule.add_rule_from.assert_called_with('192.168.0.1',
|
self.mock_rule.add_rule_from.assert_called_with('192.168.0.1',
|
||||||
16, FIP_PRI)
|
16, FIP_PRI)
|
||||||
# TODO(mrsmith): add more asserts
|
# TODO(mrsmith): add more asserts
|
||||||
|
|
||||||
def test_floating_ip_removed_dist(self):
|
@mock.patch.object(l3_agent.LinkLocalAllocator, '_write')
|
||||||
|
def test_floating_ip_removed_dist(self, write):
|
||||||
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
|
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
|
||||||
router = prepare_router_data()
|
router = prepare_router_data()
|
||||||
agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30',
|
agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30',
|
||||||
|
@ -1931,20 +2012,24 @@ class TestBasicRouterOperations(base.BaseTestCase):
|
||||||
ri.fip_2_rtr = '11.22.33.42'
|
ri.fip_2_rtr = '11.22.33.42'
|
||||||
ri.rtr_2_fip = '11.22.33.40'
|
ri.rtr_2_fip = '11.22.33.40'
|
||||||
agent.agent_gateway_port = agent_gw_port
|
agent.agent_gateway_port = agent_gw_port
|
||||||
|
s = l3_agent.LinkLocalAddressPair('169.254.30.42/31')
|
||||||
|
ri.rtr_fip_subnet = s
|
||||||
agent.floating_ip_removed_dist(ri, fip_cidr)
|
agent.floating_ip_removed_dist(ri, fip_cidr)
|
||||||
self.mock_rule.delete_rule_priority.assert_called_with(FIP_PRI)
|
self.mock_rule.delete_rule_priority.assert_called_with(FIP_PRI)
|
||||||
self.mock_ip_dev.route.delete_route.assert_called_with(fip_cidr,
|
self.mock_ip_dev.route.delete_route.assert_called_with(fip_cidr,
|
||||||
ri.rtr_2_fip)
|
str(s.ip))
|
||||||
with mock.patch.object(agent, '_destroy_fip_namespace') as f:
|
with mock.patch.object(agent, '_destroy_fip_namespace') as f:
|
||||||
ri.dist_fip_count = 1
|
ri.dist_fip_count = 1
|
||||||
agent.agent_fip_count = 1
|
agent.agent_fip_count = 1
|
||||||
fip_ns_name = agent.get_fip_ns_name(
|
fip_ns_name = agent.get_fip_ns_name(
|
||||||
str(agent._fetch_external_net_id()))
|
str(agent._fetch_external_net_id()))
|
||||||
|
ri.rtr_fip_subnet = agent.local_subnets.allocate(ri.router_id)
|
||||||
|
_, fip_to_rtr = ri.rtr_fip_subnet.get_pair()
|
||||||
agent.floating_ip_removed_dist(ri, fip_cidr)
|
agent.floating_ip_removed_dist(ri, fip_cidr)
|
||||||
self.mock_ip.del_veth.assert_called_once_with(
|
self.mock_ip.del_veth.assert_called_once_with(
|
||||||
agent.get_fip_int_device_name(router['id']))
|
agent.get_fip_int_device_name(router['id']))
|
||||||
self.mock_ip_dev.route.delete_gateway.assert_called_once_with(
|
self.mock_ip_dev.route.delete_gateway.assert_called_once_with(
|
||||||
'11.22.33.42', table=16)
|
str(fip_to_rtr.ip), table=16)
|
||||||
f.assert_called_once_with(fip_ns_name)
|
f.assert_called_once_with(fip_ns_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue