Merge "DVR: Create router to fip namespace connection based on gateway state"
This commit is contained in:
commit
8c445830ed
|
@ -15,6 +15,7 @@
|
|||
import contextlib
|
||||
import os
|
||||
|
||||
from neutron_lib import constants as lib_constants
|
||||
from oslo_concurrency import lockutils
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
|
@ -125,6 +126,13 @@ class FipNamespace(namespaces.Namespace):
|
|||
with self._fip_port_lock(interface_name):
|
||||
is_first = self.subscribe(agent_gateway_port['network_id'])
|
||||
if is_first:
|
||||
# Check for subnets that are populated for the agent
|
||||
# gateway port that was created on the server.
|
||||
if 'subnets' not in agent_gateway_port:
|
||||
self.unsubscribe(agent_gateway_port['network_id'])
|
||||
LOG.debug('DVR: Missing subnet in agent_gateway_port: %s',
|
||||
agent_gateway_port)
|
||||
return
|
||||
self._create_gateway_port(agent_gateway_port, interface_name)
|
||||
else:
|
||||
try:
|
||||
|
@ -285,10 +293,8 @@ class FipNamespace(namespaces.Namespace):
|
|||
# We reraise the exception in order to resync the router.
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.unsubscribe(self.agent_gateway_port['network_id'])
|
||||
# Reset the fip count so that the create_rtr_2_fip_link
|
||||
# is called again in this context
|
||||
ri.dist_fip_count = 0
|
||||
LOG.exception(_LE('DVR: Gateway update route in FIP namespace '
|
||||
self.agent_gateway_port = None
|
||||
LOG.exception(_LE('DVR: Gateway setup in FIP namespace '
|
||||
'failed'))
|
||||
|
||||
# Now add the filter match rule for the table.
|
||||
|
@ -351,6 +357,55 @@ class FipNamespace(namespaces.Namespace):
|
|||
if not device.addr.list(to=ip_cidr):
|
||||
device.addr.add(ip_cidr, add_broadcast=False)
|
||||
|
||||
def delete_rtr_2_fip_link(self, ri):
|
||||
"""Delete the interface between router and FloatingIP namespace."""
|
||||
LOG.debug("Delete FIP link interfaces for router: %s", ri.router_id)
|
||||
rtr_2_fip_name = self.get_rtr_ext_device_name(ri.router_id)
|
||||
fip_2_rtr_name = self.get_int_device_name(ri.router_id)
|
||||
fip_ns_name = self.get_name()
|
||||
|
||||
# remove default route entry
|
||||
if ri.rtr_fip_subnet is None:
|
||||
# see if there is a local subnet in the cache
|
||||
ri.rtr_fip_subnet = self.local_subnets.lookup(ri.router_id)
|
||||
|
||||
if ri.rtr_fip_subnet:
|
||||
rtr_2_fip, fip_2_rtr = ri.rtr_fip_subnet.get_pair()
|
||||
device = ip_lib.IPDevice(rtr_2_fip_name, namespace=ri.ns_name)
|
||||
if device.exists():
|
||||
device.route.delete_gateway(str(fip_2_rtr.ip),
|
||||
table=FIP_RT_TBL)
|
||||
if self.agent_gateway_port:
|
||||
interface_name = self.get_ext_device_name(
|
||||
self.agent_gateway_port['id'])
|
||||
fg_device = ip_lib.IPDevice(
|
||||
interface_name, namespace=fip_ns_name)
|
||||
if fg_device.exists():
|
||||
# Remove the fip namespace rules and routes associated to
|
||||
# fpr interface route table.
|
||||
tbl_index = ri._get_snat_idx(fip_2_rtr)
|
||||
fip_rt_rule = ip_lib.IPRule(namespace=fip_ns_name)
|
||||
# Flush the table
|
||||
fg_device.route.flush(lib_constants.IP_VERSION_4,
|
||||
table=tbl_index)
|
||||
fg_device.route.flush(lib_constants.IP_VERSION_6,
|
||||
table=tbl_index)
|
||||
# Remove the rule lookup
|
||||
# IP is ignored in delete, but we still require it
|
||||
# for getting the ip_version.
|
||||
fip_rt_rule.rule.delete(ip=fip_2_rtr.ip,
|
||||
iif=fip_2_rtr_name,
|
||||
table=tbl_index,
|
||||
priority=tbl_index)
|
||||
self.local_subnets.release(ri.router_id)
|
||||
ri.rtr_fip_subnet = None
|
||||
|
||||
# Check for namespace before deleting the device
|
||||
if not self.destroyed:
|
||||
fns_ip = ip_lib.IPWrapper(namespace=fip_ns_name)
|
||||
if fns_ip.device(fip_2_rtr_name).exists():
|
||||
fns_ip.del_veth(fip_2_rtr_name)
|
||||
|
||||
def create_rtr_2_fip_link(self, ri):
|
||||
"""Create interface between router and Floating IP namespace."""
|
||||
LOG.debug("Create FIP link interfaces for router %s", ri.router_id)
|
||||
|
@ -386,16 +441,14 @@ class FipNamespace(namespaces.Namespace):
|
|||
rtr_2_fip_dev.route.add_gateway(str(fip_2_rtr.ip), table=FIP_RT_TBL)
|
||||
|
||||
def scan_fip_ports(self, ri):
|
||||
# don't scan if not dvr or count is not None
|
||||
if ri.dist_fip_count is not None:
|
||||
return
|
||||
|
||||
# scan system for any existing fip ports
|
||||
ri.dist_fip_count = 0
|
||||
rtr_2_fip_interface = self.get_rtr_ext_device_name(ri.router_id)
|
||||
device = ip_lib.IPDevice(rtr_2_fip_interface, namespace=ri.ns_name)
|
||||
if device.exists():
|
||||
ri.dist_fip_count = len(ri.get_router_cidrs(device))
|
||||
if len(ri.get_router_cidrs(device)):
|
||||
self.rtr_fip_connect = True
|
||||
else:
|
||||
self.rtr_fip_connect = False
|
||||
# On upgrade, there could be stale IP addresses configured, check
|
||||
# and remove them once.
|
||||
# TODO(haleyb): this can go away after a cycle or two
|
||||
|
|
|
@ -45,7 +45,7 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase):
|
|||
self.floating_ips_dict = {}
|
||||
# Linklocal subnet for router and floating IP namespace link
|
||||
self.rtr_fip_subnet = None
|
||||
self.dist_fip_count = None
|
||||
self.rtr_fip_connect = False
|
||||
self.fip_ns = None
|
||||
self._pending_arp_set = set()
|
||||
|
||||
|
@ -104,8 +104,6 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase):
|
|||
interface_name,
|
||||
floating_ip,
|
||||
self.agent_conf.send_arp_for_ha)
|
||||
# update internal structures
|
||||
self.dist_fip_count = self.dist_fip_count + 1
|
||||
|
||||
def _add_floating_ip_rule(self, floating_ip, fixed_ip):
|
||||
rule_pr = self.fip_ns.allocate_rule_priority(floating_ip)
|
||||
|
@ -128,52 +126,18 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase):
|
|||
def floating_ip_removed_dist(self, fip_cidr):
|
||||
"""Remove floating IP from FIP namespace."""
|
||||
floating_ip = fip_cidr.split('/')[0]
|
||||
rtr_2_fip_name = self.fip_ns.get_rtr_ext_device_name(self.router_id)
|
||||
fip_2_rtr_name = self.fip_ns.get_int_device_name(self.router_id)
|
||||
if self.rtr_fip_subnet is None:
|
||||
self.rtr_fip_subnet = self.fip_ns.local_subnets.allocate(
|
||||
self.rtr_fip_subnet = self.fip_ns.local_subnets.lookup(
|
||||
self.router_id)
|
||||
if self.rtr_fip_subnet:
|
||||
rtr_2_fip, fip_2_rtr = self.rtr_fip_subnet.get_pair()
|
||||
fip_ns_name = self.fip_ns.get_name()
|
||||
self._remove_floating_ip_rule(floating_ip)
|
||||
|
||||
rtr_2_fip, fip_2_rtr = self.rtr_fip_subnet.get_pair()
|
||||
fip_ns_name = self.fip_ns.get_name()
|
||||
self._remove_floating_ip_rule(floating_ip)
|
||||
device = ip_lib.IPDevice(fip_2_rtr_name, namespace=fip_ns_name)
|
||||
|
||||
device = ip_lib.IPDevice(fip_2_rtr_name, namespace=fip_ns_name)
|
||||
|
||||
device.route.delete_route(fip_cidr, str(rtr_2_fip.ip))
|
||||
# check if this is the last FIP for this router
|
||||
self.dist_fip_count = self.dist_fip_count - 1
|
||||
if self.dist_fip_count == 0:
|
||||
#remove default route entry
|
||||
device = ip_lib.IPDevice(rtr_2_fip_name, namespace=self.ns_name)
|
||||
ns_ip = ip_lib.IPWrapper(namespace=fip_ns_name)
|
||||
device.route.delete_gateway(str(fip_2_rtr.ip),
|
||||
table=dvr_fip_ns.FIP_RT_TBL)
|
||||
if self.fip_ns.agent_gateway_port:
|
||||
interface_name = self.fip_ns.get_ext_device_name(
|
||||
self.fip_ns.agent_gateway_port['id'])
|
||||
fg_device = ip_lib.IPDevice(
|
||||
interface_name, namespace=fip_ns_name)
|
||||
if fg_device.exists():
|
||||
# Remove the fip namespace rules and routes associated to
|
||||
# fpr interface route table.
|
||||
tbl_index = self._get_snat_idx(fip_2_rtr)
|
||||
fip_rt_rule = ip_lib.IPRule(namespace=fip_ns_name)
|
||||
# Flush the table
|
||||
fg_device.route.flush(lib_constants.IP_VERSION_4,
|
||||
table=tbl_index)
|
||||
fg_device.route.flush(lib_constants.IP_VERSION_6,
|
||||
table=tbl_index)
|
||||
# Remove the rule lookup
|
||||
# IP is ignored in delete, but we still require it
|
||||
# for getting the ip_version.
|
||||
fip_rt_rule.rule.delete(ip=fip_2_rtr.ip,
|
||||
iif=fip_2_rtr_name,
|
||||
table=tbl_index,
|
||||
priority=tbl_index)
|
||||
self.fip_ns.local_subnets.release(self.router_id)
|
||||
self.rtr_fip_subnet = None
|
||||
ns_ip.del_veth(fip_2_rtr_name)
|
||||
device.route.delete_route(fip_cidr, str(rtr_2_fip.ip))
|
||||
|
||||
def floating_ip_moved_dist(self, fip):
|
||||
"""Handle floating IP move between fixed IPs."""
|
||||
|
@ -470,6 +434,10 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase):
|
|||
to_fip_interface_name = (
|
||||
self.get_external_device_interface_name(ex_gw_port))
|
||||
self.process_floating_ip_addresses(to_fip_interface_name)
|
||||
# Remove the router to fip namespace connection after the
|
||||
# gateway is removed.
|
||||
self.fip_ns.delete_rtr_2_fip_link(self)
|
||||
self.rtr_fip_connect = False
|
||||
# NOTE:_snat_redirect_remove should be only called when the
|
||||
# gateway is cleared and should not be called when the gateway
|
||||
# is moved or rescheduled.
|
||||
|
@ -530,38 +498,25 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase):
|
|||
def process_external(self):
|
||||
ex_gw_port = self.get_ex_gw_port()
|
||||
if ex_gw_port:
|
||||
self.create_dvr_fip_interfaces(ex_gw_port)
|
||||
self.create_dvr_external_gateway_on_agent(ex_gw_port)
|
||||
self.connect_rtr_2_fip()
|
||||
super(DvrLocalRouter, self).process_external()
|
||||
|
||||
def create_dvr_fip_interfaces(self, ex_gw_port):
|
||||
floating_ips = self.get_floating_ips()
|
||||
def connect_rtr_2_fip(self):
|
||||
if self.fip_ns.agent_gateway_port and not self.rtr_fip_connect:
|
||||
self.fip_ns.create_rtr_2_fip_link(self)
|
||||
self.rtr_fip_connect = True
|
||||
self.routes_updated([], self.router['routes'])
|
||||
|
||||
def create_dvr_external_gateway_on_agent(self, ex_gw_port):
|
||||
fip_agent_port = self.get_floating_agent_gw_interface(
|
||||
ex_gw_port['network_id'])
|
||||
if fip_agent_port:
|
||||
if not fip_agent_port:
|
||||
fip_agent_port = self.agent.plugin_rpc.get_agent_gateway_port(
|
||||
self.agent.context, ex_gw_port['network_id'])
|
||||
LOG.debug("FloatingIP agent gateway port received from the "
|
||||
"plugin: %s", fip_agent_port)
|
||||
if floating_ips:
|
||||
if not fip_agent_port:
|
||||
LOG.debug("No FloatingIP agent gateway port possibly due to "
|
||||
"late binding of the private port to the host, "
|
||||
"requesting agent gateway port for 'network-id' :"
|
||||
"%s", ex_gw_port['network_id'])
|
||||
fip_agent_port = self.agent.plugin_rpc.get_agent_gateway_port(
|
||||
self.agent.context, ex_gw_port['network_id'])
|
||||
if not fip_agent_port:
|
||||
LOG.error(_LE("No FloatingIP agent gateway port "
|
||||
"returned from server for 'network-id': "
|
||||
"%s"), ex_gw_port['network_id'])
|
||||
if fip_agent_port:
|
||||
if 'subnets' not in fip_agent_port:
|
||||
LOG.error(_LE('Missing subnet/agent_gateway_port'))
|
||||
else:
|
||||
self.fip_ns.create_or_update_gateway_port(fip_agent_port)
|
||||
|
||||
if (self.fip_ns.agent_gateway_port and
|
||||
(self.dist_fip_count == 0)):
|
||||
self.fip_ns.create_rtr_2_fip_link(self)
|
||||
self.routes_updated([], self.router['routes'])
|
||||
"plugin: %s", fip_agent_port)
|
||||
self.fip_ns.create_or_update_gateway_port(fip_agent_port)
|
||||
|
||||
def update_routing_table(self, operation, route):
|
||||
# TODO(Swami): The static routes should be added to the
|
||||
|
|
|
@ -64,6 +64,18 @@ class ItemAllocator(object):
|
|||
LOG.debug("Re-writing file %s due to read error", state_file)
|
||||
self._write_allocations()
|
||||
|
||||
def lookup(self, key):
|
||||
"""Try to lookup an item of ItemClass type.
|
||||
|
||||
See if there are any current or remembered allocations for the key.
|
||||
"""
|
||||
if key in self.allocations:
|
||||
return self.allocations[key]
|
||||
|
||||
if key in self.remembered:
|
||||
self.allocations[key] = self.remembered.pop(key)
|
||||
return self.allocations[key]
|
||||
|
||||
def allocate(self, key):
|
||||
"""Try to allocate an item of ItemClass type.
|
||||
|
||||
|
@ -81,12 +93,9 @@ class ItemAllocator(object):
|
|||
allocations to free the pool. This final desperate step will not
|
||||
happen often in practice.
|
||||
"""
|
||||
if key in self.allocations:
|
||||
return self.allocations[key]
|
||||
|
||||
if key in self.remembered:
|
||||
self.allocations[key] = self.remembered.pop(key)
|
||||
return self.allocations[key]
|
||||
entry = self.lookup(key)
|
||||
if entry:
|
||||
return entry
|
||||
|
||||
if not self.pool:
|
||||
# Desperate times. Try to get more in the pool.
|
||||
|
|
|
@ -491,22 +491,29 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
|
|||
|
||||
return routers
|
||||
|
||||
def _process_routers(self, context, routers):
|
||||
def _process_routers(self, context, routers, agent):
|
||||
routers_dict = {}
|
||||
snat_intfs_by_router_id = self._get_snat_sync_interfaces(
|
||||
context, [r['id'] for r in routers])
|
||||
fip_sync_interfaces = None
|
||||
LOG.debug("FIP Agent: %s ", agent.id)
|
||||
for router in routers:
|
||||
routers_dict[router['id']] = router
|
||||
if router['gw_port_id']:
|
||||
snat_router_intfs = snat_intfs_by_router_id[router['id']]
|
||||
LOG.debug("SNAT ports returned: %s ", snat_router_intfs)
|
||||
router[l3_const.SNAT_ROUTER_INTF_KEY] = snat_router_intfs
|
||||
if not fip_sync_interfaces:
|
||||
fip_sync_interfaces = self._get_fip_sync_interfaces(
|
||||
context, agent.id)
|
||||
LOG.debug("FIP Agent ports: %s", fip_sync_interfaces)
|
||||
router[l3_const.FLOATINGIP_AGENT_INTF_KEY] = (
|
||||
fip_sync_interfaces)
|
||||
|
||||
return routers_dict
|
||||
|
||||
def _process_floating_ips_dvr(self, context, routers_dict,
|
||||
floating_ips, host, agent):
|
||||
fip_sync_interfaces = None
|
||||
LOG.debug("FIP Agent : %s ", agent.id)
|
||||
floating_ips, host):
|
||||
for floating_ip in floating_ips:
|
||||
router = routers_dict.get(floating_ip['router_id'])
|
||||
if router:
|
||||
|
@ -518,12 +525,6 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
|
|||
LOG.debug("Floating IP host: %s", floating_ip['host'])
|
||||
router_floatingips.append(floating_ip)
|
||||
router[const.FLOATINGIP_KEY] = router_floatingips
|
||||
if not fip_sync_interfaces:
|
||||
fip_sync_interfaces = self._get_fip_sync_interfaces(
|
||||
context, agent.id)
|
||||
LOG.debug("FIP Agent ports: %s", fip_sync_interfaces)
|
||||
router[l3_const.FLOATINGIP_AGENT_INTF_KEY] = (
|
||||
fip_sync_interfaces)
|
||||
|
||||
def _get_fip_sync_interfaces(self, context, fip_agent_id):
|
||||
"""Query router interfaces that relate to list of router_ids."""
|
||||
|
@ -569,9 +570,9 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
|
|||
fip['dest_host'] = (
|
||||
self._get_dvr_migrating_service_port_hostid(
|
||||
context, fip['port_id'], port=vm_port))
|
||||
routers_dict = self._process_routers(context, routers)
|
||||
routers_dict = self._process_routers(context, routers, agent)
|
||||
self._process_floating_ips_dvr(context, routers_dict,
|
||||
floating_ips, host, agent)
|
||||
floating_ips, host)
|
||||
ports_to_populate = []
|
||||
for router in routers_dict.values():
|
||||
if router.get('gw_port'):
|
||||
|
|
|
@ -87,8 +87,6 @@ class TestDvrRouter(framework.L3AgentTestFramework):
|
|||
"""Test to validate snat redirect rules not cleared with snat move."""
|
||||
self.agent.conf.agent_mode = 'dvr_snat'
|
||||
router_info = self.generate_dvr_router_info(enable_snat=True)
|
||||
router_info[lib_constants.FLOATINGIP_KEY] = []
|
||||
router_info[n_const.FLOATINGIP_AGENT_INTF_KEY] = []
|
||||
router1 = self.manage_router(self.agent, router_info)
|
||||
router1.router['gw_port_host'] = ""
|
||||
self.agent._process_updated_router(router1.router)
|
||||
|
@ -96,19 +94,21 @@ class TestDvrRouter(framework.L3AgentTestFramework):
|
|||
self.assertTrue(self._namespace_exists(router_updated.ns_name))
|
||||
ns_ipr = ip_lib.IPRule(namespace=router1.ns_name)
|
||||
ip4_rules_list = ns_ipr.rule.list_rules(lib_constants.IP_VERSION_4)
|
||||
self.assertEqual(5, len(ip4_rules_list))
|
||||
# IPRule list should have 5 entries.
|
||||
self.assertEqual(6, len(ip4_rules_list))
|
||||
# IPRule list should have 6 entries.
|
||||
# Three entries from 'default', 'main' and 'local' table.
|
||||
# One rule for the floatingip.
|
||||
# The remaining 2 is for the two router interfaces(csnat ports).
|
||||
default_rules_list_count = 0
|
||||
interface_rules_list_count = 0
|
||||
for ip_rule in ip4_rules_list:
|
||||
tbl_index = ip_rule['table']
|
||||
if tbl_index in ['local', 'default', 'main']:
|
||||
if tbl_index in ['local', 'default', 'main',
|
||||
str(dvr_fip_ns.FIP_RT_TBL)]:
|
||||
default_rules_list_count = default_rules_list_count + 1
|
||||
else:
|
||||
interface_rules_list_count = interface_rules_list_count + 1
|
||||
self.assertEqual(3, default_rules_list_count)
|
||||
self.assertEqual(4, default_rules_list_count)
|
||||
self.assertEqual(2, interface_rules_list_count)
|
||||
|
||||
def test_dvr_update_gateway_port_with_no_gw_port_in_namespace(self):
|
||||
|
@ -177,13 +177,16 @@ class TestDvrRouter(framework.L3AgentTestFramework):
|
|||
self.mock_plugin_api.get_external_network_id.return_value = ext_net_id
|
||||
|
||||
# Create the fip namespace up front
|
||||
dvr_fip_ns.FipNamespace(ext_net_id,
|
||||
self.agent.conf,
|
||||
self.agent.driver,
|
||||
self.agent.use_ipv6).create()
|
||||
fip_ns = dvr_fip_ns.FipNamespace(ext_net_id,
|
||||
self.agent.conf,
|
||||
self.agent.driver,
|
||||
self.agent.use_ipv6)
|
||||
fip_ns.create()
|
||||
# Create the router with the fip, this shouldn't allow the
|
||||
# update_gateway_port to be called without the fg- port
|
||||
fip_subscribe.return_value = False
|
||||
fip_ns.agent_gateway_port = (
|
||||
router_info[n_const.FLOATINGIP_AGENT_INTF_KEY])
|
||||
# This will raise the exception and will also clear
|
||||
# subscription for the ext_net_id
|
||||
self.assertRaises(n_exc.FloatingIpSetupException,
|
||||
|
@ -191,6 +194,7 @@ class TestDvrRouter(framework.L3AgentTestFramework):
|
|||
self.agent,
|
||||
router_info)
|
||||
fip_subscribe.return_value = True
|
||||
self.manage_router(self.agent, router_info)
|
||||
# Now update the router again
|
||||
router = self.manage_router(self.agent, router_info)
|
||||
fg_port = router.fip_ns.agent_gateway_port
|
||||
|
@ -369,8 +373,10 @@ class TestDvrRouter(framework.L3AgentTestFramework):
|
|||
# gateway_port information before the l3_agent will create it.
|
||||
# The port returned needs to have the same information as
|
||||
# router_info['gw_port']
|
||||
self.mock_plugin_api.get_agent_gateway_port.return_value = router_info[
|
||||
'gw_port']
|
||||
fip_agent_gw_port = self._get_fip_agent_gw_port_for_router(
|
||||
router_info['gw_port'])
|
||||
self.mock_plugin_api.get_agent_gateway_port.return_value = (
|
||||
fip_agent_gw_port)
|
||||
|
||||
# We also need to mock the get_external_network_id method to
|
||||
# get the correct fip namespace.
|
||||
|
@ -440,12 +446,13 @@ class TestDvrRouter(framework.L3AgentTestFramework):
|
|||
enable_gw=True,
|
||||
agent=None,
|
||||
extra_routes=False,
|
||||
enable_floating_ip=True,
|
||||
**kwargs):
|
||||
if not agent:
|
||||
agent = self.agent
|
||||
router = l3_test_common.prepare_router_data(
|
||||
enable_snat=enable_snat,
|
||||
enable_floating_ip=True,
|
||||
enable_floating_ip=enable_floating_ip,
|
||||
enable_ha=enable_ha,
|
||||
extra_routes=extra_routes,
|
||||
num_internal_ports=2,
|
||||
|
@ -454,25 +461,58 @@ class TestDvrRouter(framework.L3AgentTestFramework):
|
|||
internal_ports = router.get(lib_constants.INTERFACE_KEY, [])
|
||||
router['distributed'] = True
|
||||
router['gw_port_host'] = agent.conf.host
|
||||
|
||||
floating_ip = router['_floatingips'][0]
|
||||
floating_ip['host'] = agent.conf.host
|
||||
if enable_floating_ip:
|
||||
floating_ip = router['_floatingips'][0]
|
||||
floating_ip['host'] = agent.conf.host
|
||||
if enable_gw:
|
||||
external_gw_port = router['gw_port']
|
||||
router['gw_port'][portbindings.HOST_ID] = agent.conf.host
|
||||
floating_ip['floating_network_id'] = external_gw_port['network_id']
|
||||
floating_ip['port_id'] = internal_ports[0]['id']
|
||||
floating_ip['status'] = 'ACTIVE'
|
||||
|
||||
self._add_snat_port_info_to_router(router, internal_ports)
|
||||
# FIP has a dependency on external gateway. So we need to create
|
||||
# the snat_port info and fip_agent_gw_port_info irrespective of
|
||||
# the agent type the dvr supports. The namespace creation is
|
||||
# dependent on the agent_type.
|
||||
self._add_fip_agent_gw_port_info_to_router(router,
|
||||
external_gw_port)
|
||||
if enable_floating_ip:
|
||||
floating_ip = router['_floatingips'][0]
|
||||
floating_ip['host'] = agent.conf.host
|
||||
floating_ip['floating_network_id'] = (
|
||||
external_gw_port['network_id'])
|
||||
floating_ip['port_id'] = internal_ports[0]['id']
|
||||
floating_ip['status'] = 'ACTIVE'
|
||||
|
||||
self._add_fip_agent_gw_port_info_to_router(router,
|
||||
external_gw_port)
|
||||
return router
|
||||
|
||||
def _get_fip_agent_gw_port_for_router(
|
||||
self, external_gw_port):
|
||||
# Add fip agent gateway port information to the router_info
|
||||
if external_gw_port:
|
||||
# Get values from external gateway port
|
||||
fixed_ip = external_gw_port['fixed_ips'][0]
|
||||
float_subnet = external_gw_port['subnets'][0]
|
||||
port_ip = fixed_ip['ip_address']
|
||||
# Pick an ip address which is not the same as port_ip
|
||||
fip_gw_port_ip = str(netaddr.IPAddress(port_ip) + 5)
|
||||
# Add floatingip agent gateway port info to router
|
||||
prefixlen = netaddr.IPNetwork(float_subnet['cidr']).prefixlen
|
||||
fip_agent_gw_port_info = {
|
||||
'subnets': [
|
||||
{'cidr': float_subnet['cidr'],
|
||||
'gateway_ip': float_subnet['gateway_ip'],
|
||||
'id': fixed_ip['subnet_id']}],
|
||||
'network_id': external_gw_port['network_id'],
|
||||
'device_owner': lib_constants.DEVICE_OWNER_AGENT_GW,
|
||||
'mac_address': 'fa:16:3e:80:8d:89',
|
||||
portbindings.HOST_ID: self.agent.conf.host,
|
||||
'fixed_ips': [{'subnet_id': fixed_ip['subnet_id'],
|
||||
'ip_address': fip_gw_port_ip,
|
||||
'prefixlen': prefixlen}],
|
||||
'id': framework._uuid(),
|
||||
'device_id': framework._uuid()
|
||||
}
|
||||
return fip_agent_gw_port_info
|
||||
|
||||
def _add_fip_agent_gw_port_info_to_router(self, router, external_gw_port):
|
||||
# Add fip agent gateway port information to the router_info
|
||||
fip_gw_port_list = router.get(
|
||||
|
@ -853,7 +893,10 @@ class TestDvrRouter(framework.L3AgentTestFramework):
|
|||
router1 = self.manage_router(self.agent, router_info)
|
||||
fip_ns = router1.fip_ns.get_name()
|
||||
self.assertTrue(self._namespace_exists(router1.ns_name))
|
||||
self.assertFalse(self._namespace_exists(fip_ns))
|
||||
# FIP Namespace creation does not depend on the floatingip's
|
||||
# anymore and will be created on each agent when there is
|
||||
# a valid gateway.
|
||||
self.assertTrue(self._namespace_exists(fip_ns))
|
||||
self._assert_snat_namespace_does_not_exist(router1)
|
||||
|
||||
def test_dvr_router_fip_create_for_migrating_port(self):
|
||||
|
@ -903,6 +946,26 @@ class TestDvrRouter(framework.L3AgentTestFramework):
|
|||
self.assertTrue(self._namespace_exists(fip_ns))
|
||||
self._assert_snat_namespace_does_not_exist(router1)
|
||||
|
||||
def test_dvr_router_fip_namespace_create_without_floatingip(self):
|
||||
"""Test to validate the floatingip namespace creation without fip.
|
||||
|
||||
This test validates the condition where floatingip namespace gets
|
||||
created on the agent when the gateway is added and without floatingip
|
||||
configured for the router.
|
||||
"""
|
||||
self.agent.conf.agent_mode = 'dvr'
|
||||
router_info = self.generate_dvr_router_info(enable_floating_ip=False)
|
||||
fip_agent_gw_port = self._get_fip_agent_gw_port_for_router(
|
||||
router_info['gw_port'])
|
||||
self.mock_plugin_api.get_agent_gateway_port.return_value = (
|
||||
fip_agent_gw_port)
|
||||
router1 = self.manage_router(self.agent, router_info)
|
||||
fip_ns = router1.fip_ns.get_name()
|
||||
self.assertTrue(self._namespace_exists(router1.ns_name))
|
||||
self.assertTrue(self._namespace_exists(fip_ns))
|
||||
self.assertTrue(router1.rtr_fip_connect)
|
||||
self._assert_snat_namespace_does_not_exist(router1)
|
||||
|
||||
def _assert_snat_namespace_exists(self, router):
|
||||
namespace = dvr_snat_ns.SnatNamespace.get_snat_ns_name(
|
||||
router.router_id)
|
||||
|
@ -1111,6 +1174,9 @@ class TestDvrRouter(framework.L3AgentTestFramework):
|
|||
self._assert_extra_routes(router_updated, namespace=snat_ns_name)
|
||||
if check_fpr_int_rule_delete:
|
||||
router_updated.router[lib_constants.FLOATINGIP_KEY] = []
|
||||
router_updated.router['gw_port'] = ""
|
||||
router_updated.router['gw_port_host'] = ""
|
||||
router_updated.router['external_gateway_info'] = ""
|
||||
self.agent._process_updated_router(router_updated.router)
|
||||
new_router_info = self.agent.router_info[router_updated.router_id]
|
||||
self.assertTrue(self._namespace_exists(fip_ns_name))
|
||||
|
|
|
@ -21,6 +21,7 @@ from neutron.api.rpc.handlers import l3_rpc
|
|||
from neutron.callbacks import events
|
||||
from neutron.callbacks import registry
|
||||
from neutron.callbacks import resources
|
||||
from neutron.common import constants as n_const
|
||||
from neutron.common import topics
|
||||
from neutron.extensions import external_net
|
||||
from neutron.extensions import l3
|
||||
|
@ -177,9 +178,22 @@ class L3DvrTestCase(L3DvrTestCaseBase):
|
|||
|
||||
def test_process_routers(self):
|
||||
router = self._create_router()
|
||||
result = self.l3_plugin._process_routers(self.context, [router])
|
||||
if not router.get('gw_port_id'):
|
||||
router['gw_port_id'] = 'fake_gw_id'
|
||||
self.l3_plugin._get_fip_sync_interfaces = mock.Mock(
|
||||
return_value='fip_interface')
|
||||
self.l3_plugin._get_snat_sync_interfaces = mock.Mock(
|
||||
return_value={router['id']: 'snat_interface'})
|
||||
result = self.l3_plugin._process_routers(self.context, [router],
|
||||
self.l3_agent)
|
||||
|
||||
self.assertEqual(
|
||||
router['id'], result[router['id']]['id'])
|
||||
self.assertIn(n_const.FLOATINGIP_AGENT_INTF_KEY, result[router['id']])
|
||||
self.l3_plugin._get_fip_sync_interfaces.assert_called_once_with(
|
||||
self.context, self.l3_agent['id'])
|
||||
self.l3_plugin._get_snat_sync_interfaces.assert_called_once_with(
|
||||
self.context, [router['id']])
|
||||
|
||||
def test_agent_gw_port_delete_when_last_gateway_for_ext_net_removed(self):
|
||||
kwargs = {'arg_list': (external_net.EXTERNAL,),
|
||||
|
|
|
@ -991,7 +991,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
|||
router = ri.router
|
||||
agent.host = HOSTNAME
|
||||
fake_fip_id = 'fake_fip_id'
|
||||
ri.create_dvr_fip_interfaces = mock.Mock()
|
||||
ri.create_dvr_external_gateway_on_agent = mock.Mock()
|
||||
ri.process_floating_ip_addresses = mock.Mock()
|
||||
ri.process_floating_ip_nat_rules = mock.Mock()
|
||||
ri.process_floating_ip_addresses.return_value = {
|
||||
|
@ -1070,7 +1070,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
|||
with mock.patch.object(lla.LinkLocalAllocator, '_write'):
|
||||
if ri.router['distributed']:
|
||||
ri.fip_ns = agent.get_fip_ns(ex_gw_port['network_id'])
|
||||
ri.create_dvr_fip_interfaces(ex_gw_port)
|
||||
ri.create_dvr_external_gateway_on_agent(ex_gw_port)
|
||||
fip_statuses = ri.process_floating_ip_addresses(
|
||||
mock.sentinel.interface_name)
|
||||
self.assertEqual({fip_id: lib_constants.FLOATINGIP_STATUS_ACTIVE},
|
||||
|
@ -1112,37 +1112,34 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
|||
ri = dvr_router.DvrEdgeRouter(HOSTNAME, **self.ri_kwargs)
|
||||
ext_gw_port = ri.router.get('gw_port')
|
||||
ri.fip_ns = agent.get_fip_ns(ext_gw_port['network_id'])
|
||||
ri.dist_fip_count = 0
|
||||
agent.process_router_add = mock.Mock()
|
||||
ri.fip_ns.create_rtr_2_fip_link = mock.Mock()
|
||||
with mock.patch.object(ri, 'get_floating_ips') as fips, \
|
||||
mock.patch.object(ri.fip_ns,
|
||||
'create') as create_fip, \
|
||||
'create') as create_fip, \
|
||||
mock.patch.object(ri, 'get_floating_agent_gw_interface'
|
||||
) as fip_gw_port:
|
||||
fips.return_value = fake_floatingips
|
||||
fip_gw_port.return_value = agent_gateway_port[0]
|
||||
ri.create_dvr_fip_interfaces(ext_gw_port)
|
||||
ri.create_dvr_external_gateway_on_agent(ext_gw_port)
|
||||
ri.connect_rtr_2_fip()
|
||||
self.assertTrue(fip_gw_port.called)
|
||||
self.assertTrue(fips.called)
|
||||
self.assertTrue(create_fip.called)
|
||||
self.assertEqual(agent_gateway_port[0],
|
||||
ri.fip_ns.agent_gateway_port)
|
||||
self.assertTrue(ri.rtr_fip_connect)
|
||||
# Now let us associate the fip to the router
|
||||
ri.floating_ip_added_dist(fips, "192.168.0.1/32")
|
||||
self.assertEqual(1, ri.dist_fip_count)
|
||||
# Now let us disassociate the fip from the router
|
||||
ri.floating_ip_removed_dist("192.168.0.1/32")
|
||||
self.assertEqual(0, ri.dist_fip_count)
|
||||
# Calling create_dvr_fip_interfaces again to make sure
|
||||
# that the fip namespace create is not called again.
|
||||
# Calling create_dvr_external_gateway_interfaces again to make
|
||||
# sure that the fip namespace create is not called again.
|
||||
# If the create is not called again, that would contain
|
||||
# the duplicate rules configuration in the fip namespace.
|
||||
ri.create_dvr_fip_interfaces(ext_gw_port)
|
||||
ri.create_dvr_external_gateway_on_agent(ext_gw_port)
|
||||
self.assertTrue(fip_gw_port.called)
|
||||
self.assertTrue(fips.called)
|
||||
create_fip.assert_called_once_with()
|
||||
self.assertEqual(2, ri.fip_ns.create_rtr_2_fip_link.call_count)
|
||||
self.assertEqual(1, ri.fip_ns.create_rtr_2_fip_link.call_count)
|
||||
|
||||
@mock.patch.object(lla.LinkLocalAllocator, '_write')
|
||||
def test_create_dvr_fip_interfaces_for_late_binding(self, lla_write):
|
||||
|
@ -1179,13 +1176,14 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
|||
|
||||
ext_gw_port = ri.router.get('gw_port')
|
||||
ri.fip_ns = agent.get_fip_ns(ext_gw_port['network_id'])
|
||||
ri.dist_fip_count = 0
|
||||
ri.fip_ns.subscribe = mock.Mock()
|
||||
with mock.patch.object(agent.plugin_rpc,
|
||||
'get_agent_gateway_port') as fip_gw_port:
|
||||
fip_gw_port.return_value = agent_gateway_port
|
||||
ri.create_dvr_fip_interfaces(ext_gw_port)
|
||||
ri.create_dvr_external_gateway_on_agent(ext_gw_port)
|
||||
ri.connect_rtr_2_fip()
|
||||
self.assertTrue(fip_gw_port.called)
|
||||
self.assertTrue(ri.rtr_fip_connect)
|
||||
self.assertEqual(agent_gateway_port,
|
||||
ri.fip_ns.agent_gateway_port)
|
||||
|
||||
|
@ -1224,21 +1222,20 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
|||
|
||||
ext_gw_port = ri.router.get('gw_port')
|
||||
ri.fip_ns = agent.get_fip_ns(ext_gw_port['network_id'])
|
||||
ri.dist_fip_count = 0
|
||||
ri.fip_ns.subscribe = mock.Mock()
|
||||
ri.fip_ns.agent_router_gateway = mock.Mock()
|
||||
agent.process_router_add = mock.Mock()
|
||||
|
||||
with mock.patch.object(ri, 'get_floating_ips') as fips, \
|
||||
mock.patch.object(ri, 'get_floating_agent_gw_interface'
|
||||
) as fip_gw_port:
|
||||
fips.return_value = fake_floatingips
|
||||
with mock.patch.object(
|
||||
ri,
|
||||
'get_floating_agent_gw_interface') as fip_gw_port:
|
||||
fip_gw_port.return_value = agent_gateway_port[0]
|
||||
ri.create_dvr_fip_interfaces(ext_gw_port)
|
||||
ri.create_dvr_external_gateway_on_agent(ext_gw_port)
|
||||
ri.connect_rtr_2_fip()
|
||||
self.assertTrue(fip_gw_port.called)
|
||||
self.assertTrue(fips.called)
|
||||
self.assertEqual(agent_gateway_port[0],
|
||||
ri.fip_ns.agent_gateway_port)
|
||||
self.assertTrue(ri.rtr_fip_connect)
|
||||
self.assertTrue(ri.rtr_fip_subnet)
|
||||
|
||||
@mock.patch.object(lla.LinkLocalAllocator, '_write')
|
||||
|
@ -1277,19 +1274,17 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
|||
ri.fip_ns.subscribe = mock.Mock(return_value=True)
|
||||
ri.fip_ns.agent_router_gateway = mock.Mock()
|
||||
ri.rtr_fip_subnet = None
|
||||
ri.dist_fip_count = 0
|
||||
|
||||
with mock.patch.object(ri, 'get_floating_ips') as fips,\
|
||||
mock.patch.object(ri, 'get_floating_agent_gw_interface'
|
||||
) as fip_gw_port:
|
||||
fips.return_value = fake_floatingips
|
||||
with mock.patch.object(
|
||||
ri, 'get_floating_agent_gw_interface') as fip_gw_port:
|
||||
fip_gw_port.return_value = agent_gateway_port[0]
|
||||
ri.create_dvr_fip_interfaces(ext_gw_port)
|
||||
ri.create_dvr_external_gateway_on_agent(ext_gw_port)
|
||||
ri.connect_rtr_2_fip()
|
||||
self.assertTrue(fip_gw_port.called)
|
||||
self.assertTrue(fips.called)
|
||||
self.assertEqual(agent_gateway_port[0],
|
||||
ri.fip_ns.agent_gateway_port)
|
||||
self.assertTrue(ri.rtr_fip_subnet)
|
||||
self.assertTrue(ri.rtr_fip_connect)
|
||||
|
||||
def test_process_router_cent_floating_ip_add(self):
|
||||
fake_floatingips = {'floatingips': [
|
||||
|
|
|
@ -115,6 +115,7 @@ class TestDvrFipNs(base.BaseTestCase):
|
|||
self.fip_ns._check_for_gateway_ip_change = mock.Mock(return_value=True)
|
||||
agent_gw_port = self._get_agent_gw_port()
|
||||
interface_name = self.fip_ns.get_ext_device_name(agent_gw_port['id'])
|
||||
self.fip_ns.agent_gateway_port = agent_gw_port
|
||||
self.fip_ns.create_or_update_gateway_port(agent_gw_port)
|
||||
expected = [
|
||||
mock.call(self.fip_ns.get_name(),
|
||||
|
@ -134,14 +135,13 @@ class TestDvrFipNs(base.BaseTestCase):
|
|||
@mock.patch.object(dvr_fip_ns.FipNamespace, 'unsubscribe')
|
||||
def test_update_gateway_port_raises_exception(
|
||||
self, fip_unsub, fip_delete, fip_sub, exists):
|
||||
self.fip_ns._check_for_gateway_ip_change = mock.Mock(return_value=True)
|
||||
self.fip_ns.agent_gateway_port = None
|
||||
agent_gw_port = self._get_agent_gw_port()
|
||||
self.fip_ns._create_gateway_port = mock.Mock()
|
||||
self.fip_ns.create_or_update_gateway_port(agent_gw_port)
|
||||
exists.return_value = False
|
||||
fip_sub.return_value = False
|
||||
self.fip_ns._check_for_gateway_ip_change = mock.Mock(return_value=True)
|
||||
self.fip_ns.agent_gateway_port = agent_gw_port
|
||||
|
||||
self.assertRaises(n_exc.FloatingIpSetupException,
|
||||
self.fip_ns.create_or_update_gateway_port,
|
||||
|
@ -159,7 +159,8 @@ class TestDvrFipNs(base.BaseTestCase):
|
|||
self.fip_ns.agent_gateway_port = None
|
||||
agent_gw_port = self._get_agent_gw_port()
|
||||
agent_gw_port['subnets'][0]['gateway_ip'] = '20.0.1.1'
|
||||
|
||||
self.fip_ns._check_for_gateway_ip_change = mock.Mock(return_value=True)
|
||||
self.fip_ns.agent_gateway_port = agent_gw_port
|
||||
self.fip_ns.create_or_update_gateway_port(agent_gw_port)
|
||||
|
||||
IPDevice().route.add_route.assert_called_once_with('20.0.1.1',
|
||||
|
@ -329,22 +330,15 @@ class TestDvrFipNs(base.BaseTestCase):
|
|||
|
||||
def test_scan_fip_ports_restart_fips(self):
|
||||
ri = mock.Mock()
|
||||
ri.dist_fip_count = None
|
||||
ri.floating_ips_dict = {}
|
||||
ip_list = [{'cidr': '111.2.3.4'}, {'cidr': '111.2.3.5'}]
|
||||
stale_list = ['111.2.3.7/32']
|
||||
self._test_scan_fip_ports(ri, ip_list, stale_list)
|
||||
self.assertEqual(2, ri.dist_fip_count)
|
||||
self.assertTrue(ri.rtr_fip_connect)
|
||||
|
||||
def test_scan_fip_ports_restart_none(self):
|
||||
ri = mock.Mock()
|
||||
ri.dist_fip_count = None
|
||||
ri.floating_ips_dict = {}
|
||||
ri.rtr_fip_connect = False
|
||||
self._test_scan_fip_ports(ri, [], [])
|
||||
self.assertEqual(0, ri.dist_fip_count)
|
||||
|
||||
def test_scan_fip_ports_restart_zero(self):
|
||||
ri = mock.Mock()
|
||||
ri.dist_fip_count = 0
|
||||
self._test_scan_fip_ports(ri, None, [])
|
||||
self.assertEqual(0, ri.dist_fip_count)
|
||||
self.assertFalse(ri.rtr_fip_connect)
|
||||
|
|
|
@ -177,7 +177,7 @@ class TestDvrRouterOperations(base.BaseTestCase):
|
|||
ri.fip_ns = mock.Mock()
|
||||
ri.fip_ns.subscribe.return_value = False
|
||||
ex_gw_port = {'network_id': 'fake_net_id'}
|
||||
ri.create_dvr_fip_interfaces(ex_gw_port)
|
||||
ri.create_dvr_external_gateway_on_agent(ex_gw_port)
|
||||
ri.fip_ns.create_or_update_gateway_port.assert_called_once_with(
|
||||
fip_agent_port)
|
||||
|
||||
|
@ -262,6 +262,7 @@ class TestDvrRouterOperations(base.BaseTestCase):
|
|||
def test_floating_ip_added_dist(self, mIPRule, mIPDevice, mock_adv_notif):
|
||||
router = mock.MagicMock()
|
||||
ri = self._create_router(router)
|
||||
ri.ex_gw_port = ri.router['gw_port']
|
||||
ext_net_id = _uuid()
|
||||
subnet_id = _uuid()
|
||||
agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30',
|
||||
|
@ -282,19 +283,20 @@ class TestDvrRouterOperations(base.BaseTestCase):
|
|||
'port_id': _uuid()}
|
||||
ri.fip_ns = mock.Mock()
|
||||
ri.fip_ns.agent_gateway_port = agent_gw_port
|
||||
ri.create_dvr_external_gateway_on_agent(ri.ex_gw_port)
|
||||
ri.connect_rtr_2_fip()
|
||||
self.assertTrue(ri.rtr_fip_connect)
|
||||
ri.fip_ns.allocate_rule_priority.return_value = FIP_PRI
|
||||
subnet = lla.LinkLocalAddressPair('169.254.30.42/31')
|
||||
ri.rtr_fip_subnet = subnet
|
||||
ri.fip_ns.local_subnets = mock.Mock()
|
||||
ri.fip_ns.local_subnets.allocate.return_value = subnet
|
||||
ri.dist_fip_count = 0
|
||||
ip_cidr = common_utils.ip_to_cidr(fip['floating_ip_address'])
|
||||
ri.floating_ip_added_dist(fip, ip_cidr)
|
||||
mIPRule().rule.add.assert_called_with(ip='192.168.0.1',
|
||||
table=16,
|
||||
priority=FIP_PRI)
|
||||
ri.fip_ns.local_subnets.allocate.assert_not_called()
|
||||
self.assertEqual(1, ri.dist_fip_count)
|
||||
|
||||
# Validate that fip_ns.local_subnets is called when
|
||||
# rtr_fip_subnet is None
|
||||
|
@ -312,7 +314,7 @@ class TestDvrRouterOperations(base.BaseTestCase):
|
|||
def test_floating_ip_removed_dist(self, mIPRule, mIPDevice, mIPWrapper):
|
||||
router = mock.MagicMock()
|
||||
ri = self._create_router(router)
|
||||
|
||||
ri.ex_gw_port = ri.router['gw_port']
|
||||
subnet_id = _uuid()
|
||||
agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30',
|
||||
'prefixlen': 24,
|
||||
|
@ -324,8 +326,6 @@ class TestDvrRouterOperations(base.BaseTestCase):
|
|||
'network_id': _uuid(),
|
||||
'mac_address': 'ca:fe:de:ad:be:ef'}
|
||||
fip_cidr = '11.22.33.44/24'
|
||||
|
||||
ri.dist_fip_count = 2
|
||||
ri.fip_ns = mock.Mock()
|
||||
ri.fip_ns.get_name.return_value = 'fip_ns_name'
|
||||
ri.floating_ips_dict['11.22.33.44'] = FIP_PRI
|
||||
|
@ -341,20 +341,6 @@ class TestDvrRouterOperations(base.BaseTestCase):
|
|||
mIPDevice().route.delete_route.assert_called_with(fip_cidr, str(s.ip))
|
||||
ri.fip_ns.local_subnets.allocate.assert_not_called()
|
||||
|
||||
ri.dist_fip_count = 1
|
||||
s1 = lla.LinkLocalAddressPair('15.1.2.3/32')
|
||||
ri.rtr_fip_subnet = None
|
||||
ri.fip_ns.local_subnets.allocate.return_value = s1
|
||||
_, fip_to_rtr = s1.get_pair()
|
||||
fip_ns = ri.fip_ns
|
||||
ri.floating_ip_removed_dist(fip_cidr)
|
||||
self.assertTrue(fip_ns.destroyed)
|
||||
mIPWrapper().del_veth.assert_called_once_with(
|
||||
fip_ns.get_int_device_name(router['id']))
|
||||
self.assertEqual(1, mIPDevice().route.delete_gateway.call_count)
|
||||
self.assertFalse(ri.fip_ns.unsubscribe.called)
|
||||
ri.fip_ns.local_subnets.allocate.assert_called_once_with(ri.router_id)
|
||||
|
||||
@mock.patch.object(ip_lib, 'IPRule')
|
||||
def test_floating_ip_moved_dist(self, mIPRule):
|
||||
router = mock.MagicMock()
|
||||
|
@ -622,7 +608,6 @@ class TestDvrRouterOperations(base.BaseTestCase):
|
|||
self._set_ri_kwargs(agent, router['id'], router)
|
||||
ri = dvr_router.DvrLocalRouter(HOSTNAME, **self.ri_kwargs)
|
||||
ri.iptables_manager.ipv4['nat'] = mock.MagicMock()
|
||||
ri.dist_fip_count = 0
|
||||
fip_ns = agent.get_fip_ns(mock.sentinel.ext_net_id)
|
||||
subnet_id = _uuid()
|
||||
fip_ns.agent_gateway_port = (
|
||||
|
@ -701,7 +686,6 @@ class TestDvrRouterOperations(base.BaseTestCase):
|
|||
|
||||
vm_floating_ip = '19.4.4.2'
|
||||
ri.floating_ips_dict[vm_floating_ip] = FIP_PRI
|
||||
ri.dist_fip_count = 1
|
||||
ri.rtr_fip_subnet = ri.fip_ns.local_subnets.allocate(ri.router_id)
|
||||
_, fip_to_rtr = ri.rtr_fip_subnet.get_pair()
|
||||
self.mock_ip.get_devices.return_value = [
|
||||
|
@ -709,11 +693,9 @@ class TestDvrRouterOperations(base.BaseTestCase):
|
|||
ri.get_router_cidrs = mock.Mock(
|
||||
return_value={vm_floating_ip + '/32', '19.4.4.1/24'})
|
||||
self.device_exists.return_value = True
|
||||
|
||||
ri.external_gateway_removed(
|
||||
ri.ex_gw_port,
|
||||
ri.get_external_device_name(ri.ex_gw_port['id']))
|
||||
|
||||
ri.remove_floating_ip.assert_called_once_with(self.mock_ip_dev,
|
||||
'19.4.4.2/32')
|
||||
|
||||
|
|
|
@ -66,16 +66,20 @@ class TestItemAllocator(base.BaseTestCase):
|
|||
self.assertEqual({}, a.allocations)
|
||||
self.assertTrue(write.called)
|
||||
|
||||
def test_allocate(self):
|
||||
def test_allocate_and_lookup(self):
|
||||
test_pool = set([TestObject(33000), TestObject(33001)])
|
||||
a = ia.ItemAllocator('/file', TestObject, test_pool)
|
||||
with mock.patch.object(ia.ItemAllocator, '_write') as write:
|
||||
test_object = a.allocate('test')
|
||||
|
||||
# a lookup should find the same object
|
||||
lookup_object = a.lookup('test')
|
||||
|
||||
self.assertIn('test', a.allocations)
|
||||
self.assertIn(test_object, a.allocations.values())
|
||||
self.assertNotIn(test_object, a.pool)
|
||||
self.assertTrue(write.called)
|
||||
self.assertEqual(test_object, lookup_object)
|
||||
|
||||
def test_allocate_repeated_call_with_same_key(self):
|
||||
test_pool = set([TestObject(33000), TestObject(33001),
|
||||
|
|
|
@ -24,7 +24,6 @@ from oslo_utils import uuidutils
|
|||
from neutron.callbacks import events
|
||||
from neutron.callbacks import registry
|
||||
from neutron.callbacks import resources
|
||||
from neutron.common import constants as n_const
|
||||
from neutron.db import agents_db
|
||||
from neutron.db import common_db_mixin
|
||||
from neutron.db import l3_agentschedulers_db
|
||||
|
@ -381,29 +380,20 @@ class L3DvrTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
|||
return_value=fipagent)
|
||||
self.mixin._get_fip_sync_interfaces = mock.Mock(
|
||||
return_value='fip_interface')
|
||||
agent = mock.Mock()
|
||||
agent.id = fipagent['id']
|
||||
|
||||
self.mixin._process_floating_ips_dvr(self.ctx, routers, [floatingip],
|
||||
hostid, agent)
|
||||
hostid)
|
||||
return (router, floatingip)
|
||||
|
||||
def test_floatingip_on_port_not_host(self):
|
||||
router, fip = self._floatingip_on_port_test_setup(None)
|
||||
|
||||
self.assertNotIn(const.FLOATINGIP_KEY, router)
|
||||
self.assertNotIn(n_const.FLOATINGIP_AGENT_INTF_KEY, router)
|
||||
|
||||
def test_floatingip_on_port_with_host(self):
|
||||
router, fip = self._floatingip_on_port_test_setup(_uuid())
|
||||
|
||||
self.assertTrue(self.mixin._get_fip_sync_interfaces.called)
|
||||
|
||||
self.assertIn(const.FLOATINGIP_KEY, router)
|
||||
self.assertIn(n_const.FLOATINGIP_AGENT_INTF_KEY, router)
|
||||
self.assertIn(fip, router[const.FLOATINGIP_KEY])
|
||||
self.assertIn('fip_interface',
|
||||
router[n_const.FLOATINGIP_AGENT_INTF_KEY])
|
||||
|
||||
def _setup_test_create_floatingip(
|
||||
self, fip, floatingip_db, router_db):
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
prelude: >
|
||||
Add DVR Floating IP (FIP) Namespace creation event
|
||||
on all nodes, based on the gateway configuration.
|
||||
features:
|
||||
- Proactively create Floating IP Namespace on all compute nodes
|
||||
when a gateway is configured.
|
||||
issues:
|
||||
- This might consume public IP Address, but by using
|
||||
subnet service-types as explained in the docs below
|
||||
https://docs.openstack.org/networking-guide/config-service-subnets.html
|
||||
consumers can use the private IPs for floating IP agent gateway ports
|
||||
and need not consume any public IP addresses.
|
Loading…
Reference in New Issue