#
import eventlet
-import netaddr
from oslo_config import cfg
from oslo_log import log as logging
import oslo_messaging
self.event_observers.notify(
adv_svc.AdvancedService.after_router_removed, ri)
- def _process_external_gateway(self, ri):
- ex_gw_port = ri.get_ex_gw_port()
- ex_gw_port_id = (ex_gw_port and ex_gw_port['id'] or
- ri.ex_gw_port and ri.ex_gw_port['id'])
-
- interface_name = None
- if ex_gw_port_id:
- interface_name = self.get_external_device_name(ex_gw_port_id)
- if ex_gw_port:
- def _gateway_ports_equal(port1, port2):
- def _get_filtered_dict(d, ignore):
- return dict((k, v) for k, v in d.iteritems()
- if k not in ignore)
-
- keys_to_ignore = set(['binding:host_id'])
- port1_filtered = _get_filtered_dict(port1, keys_to_ignore)
- port2_filtered = _get_filtered_dict(port2, keys_to_ignore)
- return port1_filtered == port2_filtered
-
- ri._set_subnet_info(ex_gw_port)
- if not ri.ex_gw_port:
- self.external_gateway_added(ri, ex_gw_port, interface_name)
- elif not _gateway_ports_equal(ex_gw_port, ri.ex_gw_port):
- self.external_gateway_updated(ri, ex_gw_port, interface_name)
- elif not ex_gw_port and ri.ex_gw_port:
- self.external_gateway_removed(ri, ri.ex_gw_port, interface_name)
-
- existing_devices = ri._get_existing_devices()
- stale_devs = [dev for dev in existing_devices
- if dev.startswith(EXTERNAL_DEV_PREFIX)
- and dev != interface_name]
- for stale_dev in stale_devs:
- LOG.debug('Deleting stale external router device: %s',
- stale_dev)
- self.driver.unplug(stale_dev,
- bridge=self.conf.external_network_bridge,
- namespace=ri.ns_name,
- prefix=EXTERNAL_DEV_PREFIX)
-
- # Process SNAT rules for external gateway
- if (not ri.router['distributed'] or
- ex_gw_port and ri.get_gw_port_host() == self.host):
- ri.perform_snat_action(self._handle_router_snat_rules,
- interface_name)
-
- def _update_fip_statuses(self, ri, existing_floating_ips, fip_statuses):
+ def update_fip_statuses(self, ri, existing_floating_ips, fip_statuses):
# Identify floating IPs which were disabled
ri.floating_ips = set(fip_statuses.keys())
for fip_id in existing_floating_ips - ri.floating_ips:
else:
ri.disable_keepalived()
- def _process_external(self, ri):
- existing_floating_ips = ri.floating_ips
- try:
- with ri.iptables_manager.defer_apply():
- self._process_external_gateway(ri)
- ex_gw_port = ri.get_ex_gw_port()
- # TODO(Carl) Return after setting existing_floating_ips and
- # still call _update_fip_statuses?
- if not ex_gw_port:
- return
-
- # Process SNAT/DNAT rules and addresses for floating IPs
- if ri.router['distributed']:
- self.create_dvr_fip_interfaces(ri, ex_gw_port)
- ri.process_snat_dnat_for_fip()
-
- # Once NAT rules for floating IPs are safely in place
- # configure their addresses on the external gateway port
- interface_name = self._get_external_device_interface_name(
- ri, ex_gw_port)
- fip_statuses = ri.configure_fip_addresses(interface_name)
-
- except (n_exc.FloatingIpSetupException,
- n_exc.IpTablesApplyException) as e:
- # All floating IPs must be put in error state
- LOG.exception(e)
- fip_statuses = ri.put_fips_in_error_state()
-
- self._update_fip_statuses(ri, existing_floating_ips, fip_statuses)
-
@common_utils.exception_logger()
def process_router(self, ri):
# TODO(mrsmith) - we shouldn't need to check here
ri.fip_ns = self.get_fip_ns(ex_gw_port['network_id'])
ri.fip_ns.scan_fip_ports(ri)
ri._process_internal_ports()
- self._process_external(ri)
+ ri.process_external(self)
# Process static routes for router
ri.routes_updated()
ri.snat_ports = ri.router.get(l3_constants.SNAT_ROUTER_INTF_KEY, [])
ri.enable_snat = ri.router.get('enable_snat')
- def _handle_router_snat_rules(self, ri, ex_gw_port,
- interface_name, action):
- # Remove all the rules
- # This is safe because if use_namespaces is set as False
- # then the agent can only configure one router, otherwise
- # each router's SNAT rules will be in their own namespace
- if not ri.router['distributed']:
- iptables_manager = ri.iptables_manager
- elif ri.snat_iptables_manager:
- iptables_manager = ri.snat_iptables_manager
- else:
- LOG.debug("DVR router: no snat rules to be handled")
- return
-
- iptables_manager.ipv4['nat'].empty_chain('POSTROUTING')
- iptables_manager.ipv4['nat'].empty_chain('snat')
-
- if not ri.router['distributed']:
- # Add back the jump to float-snat
- iptables_manager.ipv4['nat'].add_rule('snat', '-j $float-snat')
-
- # And add them back if the action is add_rules
- if action == 'add_rules' and ex_gw_port:
- # ex_gw_port should not be None in this case
- # NAT rules are added only if ex_gw_port has an IPv4 address
- for ip_addr in ex_gw_port['fixed_ips']:
- ex_gw_ip = ip_addr['ip_address']
- if netaddr.IPAddress(ex_gw_ip).version == 4:
- rules = self.external_gateway_nat_rules(ex_gw_ip,
- interface_name)
- for rule in rules:
- iptables_manager.ipv4['nat'].add_rule(*rule)
- break
- iptables_manager.apply()
-
- def create_dvr_fip_interfaces(self, ri, ex_gw_port):
- floating_ips = ri.get_floating_ips()
- fip_agent_port = ri.get_floating_agent_gw_interface(
- ex_gw_port['network_id'])
- LOG.debug("FloatingIP agent gateway port received from the plugin: "
- "%s", fip_agent_port)
- if floating_ips:
- is_first = ri.fip_ns.subscribe(ri.router_id)
- if is_first and fip_agent_port:
- if 'subnet' not in fip_agent_port:
- LOG.error(_LE('Missing subnet/agent_gateway_port'))
- else:
- ri._set_subnet_info(fip_agent_port)
- ri.fip_ns.create_gateway_port(fip_agent_port)
-
- if ri.fip_ns.agent_gateway_port and floating_ips:
- if ri.dist_fip_count == 0:
- ri.fip_ns.create_rtr_2_fip_link(ri)
-
- # kicks the FW Agent to add rules for the IR namespace if
- # configured
- self.process_router_add(ri)
-
- def _get_external_device_interface_name(self, ri, ex_gw_port):
- if ri.router['distributed']:
- fip_int = ri.fip_ns.get_int_device_name(ri.router_id)
- if ip_lib.device_exists(fip_int, namespace=ri.fip_ns.get_name()):
- return ri.fip_ns.get_rtr_ext_device_name(ri.router_id)
- else:
- return self.get_external_device_name(ex_gw_port['id'])
-
- def get_external_device_name(self, port_id):
- return (EXTERNAL_DEV_PREFIX + port_id)[:self.driver.DEV_NAME_LEN]
-
- def external_gateway_added(self, ri, ex_gw_port, interface_name):
- if ri.router['distributed']:
- ip_wrapr = ip_lib.IPWrapper(namespace=ri.ns_name)
- ip_wrapr.netns.execute(['sysctl', '-w',
- 'net.ipv4.conf.all.send_redirects=0'])
- snat_ports = ri.get_snat_interfaces()
- for p in ri.internal_ports:
- gateway = ri._map_internal_interfaces(p, snat_ports)
- id_name = ri.get_internal_device_name(p['id'])
- if gateway:
- ri._snat_redirect_add(
- gateway['fixed_ips'][0]['ip_address'], p, id_name)
-
- if (self.conf.agent_mode == l3_constants.L3_AGENT_MODE_DVR_SNAT and
- ri.get_gw_port_host() == self.host):
- self._create_dvr_gateway(ri, ex_gw_port, interface_name,
- snat_ports)
- for port in snat_ports:
- for ip in port['fixed_ips']:
- ri._update_arp_entry(ip['ip_address'],
- port['mac_address'],
- ip['subnet_id'],
- 'add')
- return
-
- # Compute a list of addresses this router is supposed to have.
- # This avoids unnecessarily removing those addresses and
- # causing a momentarily network outage.
- floating_ips = ri.get_floating_ips()
- preserve_ips = [common_utils.ip_to_cidr(ip['floating_ip_address'])
- for ip in floating_ips]
-
- self._external_gateway_added(ri, ex_gw_port, interface_name,
- ri.ns_name, preserve_ips)
-
- if ri.is_ha:
- ri._ha_external_gateway_added(ex_gw_port, interface_name)
- ri._ha_disable_addressing_on_interface(interface_name)
-
- def external_gateway_updated(self, ri, ex_gw_port, interface_name):
- preserve_ips = []
- if ri.router['distributed']:
- if (self.conf.agent_mode == l3_constants.L3_AGENT_MODE_DVR_SNAT and
- ri.get_gw_port_host() == self.host):
- ns_name = ri.snat_namespace.name
- else:
- # no centralized SNAT gateway for this node/agent
- LOG.debug("not hosting snat for router: %s", ri.router['id'])
- return
- else:
- ns_name = ri.ns_name
- floating_ips = ri.get_floating_ips()
- preserve_ips = [common_utils.ip_to_cidr(ip['floating_ip_address'])
- for ip in floating_ips]
-
- self._external_gateway_added(ri, ex_gw_port, interface_name,
- ns_name, preserve_ips)
-
- if ri.is_ha:
- ri._ha_external_gateway_updated(ex_gw_port, interface_name)
-
- def _external_gateway_added(self, ri, ex_gw_port, interface_name,
- ns_name, preserve_ips):
- if not ip_lib.device_exists(interface_name, namespace=ns_name):
- self.driver.plug(ex_gw_port['network_id'],
- ex_gw_port['id'], interface_name,
- ex_gw_port['mac_address'],
- bridge=self.conf.external_network_bridge,
- namespace=ns_name,
- prefix=EXTERNAL_DEV_PREFIX)
-
- if not ri.is_ha:
- self.driver.init_l3(
- interface_name, [ex_gw_port['ip_cidr']], namespace=ns_name,
- gateway=ex_gw_port['subnet'].get('gateway_ip'),
- extra_subnets=ex_gw_port.get('extra_subnets', []),
- preserve_ips=preserve_ips)
- ip_address = ex_gw_port['ip_cidr'].split('/')[0]
- ip_lib.send_gratuitous_arp(ns_name,
- interface_name,
- ip_address,
- self.conf.send_arp_for_ha)
-
- def external_gateway_removed(self, ri, ex_gw_port, interface_name):
- if ri.router['distributed']:
- # TODO(Carl) Should this be calling process_snat_dnat_for_fip?
- ri.process_floating_ip_nat_rules()
- if ri.fip_ns:
- to_fip_interface_name = (
- self._get_external_device_interface_name(ri, ex_gw_port))
- ri.process_floating_ip_addresses(to_fip_interface_name)
- snat_ports = ri.get_snat_interfaces()
- for p in ri.internal_ports:
- gateway = self._map_internal_interfaces(ri, p, snat_ports)
- internal_interface = ri.get_internal_device_name(p['id'])
- ri._snat_redirect_remove(gateway['fixed_ips'][0]['ip_address'],
- p,
- internal_interface)
-
- if (self.conf.agent_mode == l3_constants.L3_AGENT_MODE_DVR_SNAT
- and ri.get_gw_port_host() == self.host):
- ns_name = ri.snat_namespace.name
- else:
- # not hosting agent - no work to do
- LOG.debug('DVR: CSNAT not hosted: %s', ex_gw_port)
- return
- else:
- ns_name = ri.ns_name
-
- if ri.is_ha:
- ri._ha_external_gateway_removed(interface_name)
-
- self.driver.unplug(interface_name,
- bridge=self.conf.external_network_bridge,
- namespace=ns_name,
- prefix=EXTERNAL_DEV_PREFIX)
- if ri.router['distributed']:
- ri.delete_snat_namespace()
-
- def external_gateway_nat_rules(self, ex_gw_ip, interface_name):
- rules = [('POSTROUTING', '! -i %(interface_name)s '
- '! -o %(interface_name)s -m conntrack ! '
- '--ctstate DNAT -j ACCEPT' %
- {'interface_name': interface_name}),
- ('snat', '-o %s -j SNAT --to-source %s' %
- (interface_name, ex_gw_ip))]
- return rules
-
def router_deleted(self, context, router_id):
"""Deal with router deletion RPC message."""
LOG.debug('Got router deleted notification for %s', router_id)
from neutron.agent.l3 import dvr_fip_ns
from neutron.agent.l3 import dvr_snat_ns
-from neutron.agent.linux import iptables_manager
LOG = logging.getLogger(__name__)
def get_ports_by_subnet(self, subnet_id):
return self.plugin_rpc.get_ports_by_subnet(self.context, subnet_id)
- def _create_dvr_gateway(self, ri, ex_gw_port, gw_interface_name,
- snat_ports):
- """Create SNAT namespace."""
- snat_ns = ri.create_snat_namespace()
- # connect snat_ports to br_int from SNAT namespace
- for port in snat_ports:
- # create interface_name
- ri._set_subnet_info(port)
- interface_name = ri.get_snat_int_device_name(port['id'])
- # TODO(Carl) calling private method on router. Will fix soon.
- ri._internal_network_added(snat_ns.name, port['network_id'],
- port['id'], port['ip_cidr'],
- port['mac_address'], interface_name,
- SNAT_INT_DEV_PREFIX)
- self._external_gateway_added(ri, ex_gw_port, gw_interface_name,
- snat_ns.name, preserve_ips=[])
- ri.snat_iptables_manager = iptables_manager.IptablesManager(
- namespace=snat_ns.name,
- use_ipv6=self.use_ipv6)
- # kicks the FW Agent to add rules for the snat namespace
- self.process_router_add(ri)
-
def add_arp_entry(self, context, payload):
"""Add arp entry into router namespace. Called from RPC."""
router_id = payload['router_id']
from neutron.agent.l3 import dvr_snat_ns
from neutron.agent.l3 import router_info as router
from neutron.agent.linux import ip_lib
+from neutron.agent.linux import iptables_manager
from neutron.common import constants as l3_constants
from neutron.common import utils as common_utils
from neutron.i18n import _LE
self.snat_namespace.create()
return self.snat_namespace
- def delete_snat_namespace(self):
- # TODO(mlavalle): in the near future, this method should contain the
- # code in the L3 agent that removes an external gateway for a dvr. The
- # first step is to move the deletion of the snat namespace here
- self.snat_namespace.delete()
- self.snat_namespace = None
-
def _get_internal_port(self, subnet_id):
"""Return internal router port based on subnet_id."""
router_ports = self.router.get(l3_constants.INTERFACE_KEY, [])
self.router['id'])
return host
+ def _is_this_snat_host(self):
+ # TODO(Carl) This is a sign that dvr needs two router classes.
+ mode = self.agent_conf.agent_mode
+ return (mode == l3_constants.L3_AGENT_MODE_DVR_SNAT
+ and self.get_gw_port_host() == self.host)
+
def internal_network_added(self, port):
super(DvrRouter, self).internal_network_added(port)
port,
interface_name)
- # TODO(Carl) This is a sign that dvr needs two router classes.
- is_this_snat_host = (self.agent_conf.agent_mode == 'dvr_snat' and
- self.get_gw_port_host() == self.host)
- if not is_this_snat_host:
+ if not self._is_this_snat_host():
return
ns_name = dvr_snat_ns.SnatNamespace.get_snat_ns_name(self.router['id'])
port,
interface_name)
- is_this_snat_host = (self.agent_conf.agent_mode == 'dvr_snat' and
- self.ex_gw_port['binding:host_id'] == self.host)
+ mode = self.agent_conf.agent_mode
+ is_this_snat_host = (mode == l3_constants.L3_AGENT_MODE_DVR_SNAT
+ and self.ex_gw_port['binding:host_id'] == self.host)
if not is_this_snat_host:
return
fip_ports = self.router.get(l3_constants.FLOATINGIP_AGENT_INTF_KEY, [])
return next(
(p for p in fip_ports if p['network_id'] == ext_net_id), None)
+
+ def get_external_device_interface_name(self, ex_gw_port):
+ fip_int = self.fip_ns.get_int_device_name(self.router_id)
+ if ip_lib.device_exists(fip_int, namespace=self.fip_ns.get_name()):
+ return self.fip_ns.get_rtr_ext_device_name(self.router_id)
+
+ def _create_dvr_gateway(self, ex_gw_port, gw_interface_name,
+ snat_ports):
+ """Create SNAT namespace."""
+ snat_ns = self.create_snat_namespace()
+ # connect snat_ports to br_int from SNAT namespace
+ for port in snat_ports:
+ # create interface_name
+ self._set_subnet_info(port)
+ interface_name = self.get_snat_int_device_name(port['id'])
+ self._internal_network_added(snat_ns.name, port['network_id'],
+ port['id'], port['ip_cidr'],
+ port['mac_address'], interface_name,
+ dvr_snat_ns.SNAT_INT_DEV_PREFIX)
+ self._external_gateway_added(ex_gw_port, gw_interface_name,
+ snat_ns.name, preserve_ips=[])
+ self.snat_iptables_manager = iptables_manager.IptablesManager(
+ namespace=snat_ns.name,
+ use_ipv6=self.use_ipv6)
+ # kicks the FW Agent to add rules for the snat namespace
+ self.agent.process_router_add(self)
+
+ def external_gateway_added(self, ex_gw_port, interface_name):
+ # TODO(Carl) Refactor external_gateway_added/updated/removed to use
+ # super class implementation where possible. Looks like preserve_ips,
+ # and ns_name are the key differences.
+ ip_wrapr = ip_lib.IPWrapper(namespace=self.ns_name)
+ ip_wrapr.netns.execute(['sysctl', '-w',
+ 'net.ipv4.conf.all.send_redirects=0'])
+ snat_ports = self.get_snat_interfaces()
+ for p in self.internal_ports:
+ gateway = self._map_internal_interfaces(p, snat_ports)
+ id_name = self.get_internal_device_name(p['id'])
+ if gateway:
+ self._snat_redirect_add(
+ gateway['fixed_ips'][0]['ip_address'], p, id_name)
+
+ if self._is_this_snat_host():
+ self._create_dvr_gateway(ex_gw_port, interface_name, snat_ports)
+
+ for port in snat_ports:
+ for ip in port['fixed_ips']:
+ self._update_arp_entry(ip['ip_address'],
+ port['mac_address'],
+ ip['subnet_id'],
+ 'add')
+
+ def external_gateway_updated(self, ex_gw_port, interface_name):
+ if not self._is_this_snat_host():
+ # no centralized SNAT gateway for this node/agent
+ LOG.debug("not hosting snat for router: %s", self.router['id'])
+ return
+
+ self._external_gateway_added(ex_gw_port,
+ interface_name,
+ self.snat_namespace.name,
+ preserve_ips=[])
+
+ def external_gateway_removed(self, ex_gw_port, interface_name):
+ # TODO(Carl) Should this be calling process_snat_dnat_for_fip?
+ self.process_floating_ip_nat_rules()
+ if self.fip_ns:
+ to_fip_interface_name = (
+ self.get_external_device_interface_name(ex_gw_port))
+ self.process_floating_ip_addresses(to_fip_interface_name)
+ snat_ports = self.get_snat_interfaces()
+ for p in self.internal_ports:
+ gateway = self._map_internal_interfaces(p, snat_ports)
+ internal_interface = self.get_internal_device_name(p['id'])
+ self._snat_redirect_remove(gateway['fixed_ips'][0]['ip_address'],
+ p,
+ internal_interface)
+
+ if not self._is_this_snat_host():
+ # no centralized SNAT gateway for this node/agent
+ LOG.debug("not hosting snat for router: %s", self.router['id'])
+ return
+
+ self.driver.unplug(interface_name,
+ bridge=self.agent_conf.external_network_bridge,
+ namespace=self.snat_namespace.name,
+ prefix=router.EXTERNAL_DEV_PREFIX)
+
+ self.snat_namespace.delete()
+ self.snat_namespace = None
+
+ def _handle_router_snat_rules(self, ex_gw_port,
+ interface_name, action):
+ if not self.snat_iptables_manager:
+ LOG.debug("DVR router: no snat rules to be handled")
+ return
+
+ with self.snat_iptables_manager.defer_apply():
+ self._empty_snat_chains(self.snat_iptables_manager)
+
+ # NOTE DVR doesn't add the jump to float snat like the super class.
+
+ self._add_snat_rules(ex_gw_port, self.snat_iptables_manager,
+ interface_name, action)
+
+ def perform_snat_action(self, snat_callback, *args):
+ # NOTE DVR skips this step in a few cases...
+ if not self.get_ex_gw_port():
+ return
+ if self.get_gw_port_host() != self.host:
+ return
+
+ super(DvrRouter, self).perform_snat_action(snat_callback, *args)
+
+ def create_dvr_fip_interfaces(self, ex_gw_port):
+ floating_ips = self.get_floating_ips()
+ fip_agent_port = self.get_floating_agent_gw_interface(
+ ex_gw_port['network_id'])
+ LOG.debug("FloatingIP agent gateway port received from the plugin: "
+ "%s", fip_agent_port)
+ if floating_ips:
+ is_first = self.fip_ns.subscribe(self.router_id)
+ if is_first and fip_agent_port:
+ if 'subnet' not in fip_agent_port:
+ LOG.error(_LE('Missing subnet/agent_gateway_port'))
+ else:
+ self._set_subnet_info(fip_agent_port)
+ self.fip_ns.create_gateway_port(fip_agent_port)
+
+ if self.fip_ns.agent_gateway_port and floating_ips:
+ if self.dist_fip_count == 0:
+ self.fip_ns.create_rtr_2_fip_link(self)
+
+ # kicks the FW Agent to add rules for the IR namespace if
+ # configured
+ self.agent.process_router_add(self)
def get_router_cidrs(self, device):
return set(self._ha_get_existing_cidrs(device.name))
- def _ha_external_gateway_removed(self, interface_name):
- self._clear_vips(interface_name)
-
def routes_updated(self):
new_routes = self.router['routes']
return False
return True
- def _ha_disable_addressing_on_interface(self, interface_name):
+ def _disable_ipv6_addressing_on_interface(self, interface_name):
"""Disable IPv6 link local addressing on the device and add it as
a VIP to keepalived. This means that the IPv6 link local address
will only be present on the master.
self._remove_vip(ipv6_lladdr)
self._add_vip(ipv6_lladdr, interface_name, scope='link')
- def _ha_external_gateway_added(self, ex_gw_port, interface_name):
+ def _add_gateway_vip(self, ex_gw_port, interface_name):
self._add_vip(ex_gw_port['ip_cidr'], interface_name)
self._add_default_gw_virtual_route(ex_gw_port, interface_name)
- def _ha_external_gateway_updated(self, ex_gw_port, interface_name):
- old_gateway_cidr = self.ex_gw_port['ip_cidr']
- self._remove_vip(old_gateway_cidr)
- self._ha_external_gateway_added(ex_gw_port, interface_name)
-
def add_floating_ip(self, fip, interface_name, device):
fip_ip = fip['floating_ip_address']
ip_cidr = common_utils.ip_to_cidr(fip_ip)
namespace=self.ns_name,
prefix=router.INTERNAL_DEV_PREFIX)
- self._ha_disable_addressing_on_interface(interface_name)
+ self._disable_ipv6_addressing_on_interface(interface_name)
self._add_vip(port['ip_cidr'], interface_name)
def internal_network_removed(self, port):
state = 'master' if ha_cidr in cidrs else 'backup'
self.ha_state = state
callback(self.router_id, state)
+
+ def external_gateway_added(self, ex_gw_port, interface_name):
+ self._plug_external_gateway(ex_gw_port, interface_name, self.ns_name)
+ self._add_gateway_vip(ex_gw_port, interface_name)
+ self._disable_ipv6_addressing_on_interface(interface_name)
+
+ def external_gateway_updated(self, ex_gw_port, interface_name):
+ self._plug_external_gateway(ex_gw_port, interface_name, self.ns_name)
+ old_gateway_cidr = self.ex_gw_port['ip_cidr']
+ self._remove_vip(old_gateway_cidr)
+ self._add_gateway_vip(ex_gw_port, interface_name)
+
+ def external_gateway_removed(self, ex_gw_port, interface_name):
+ self._clear_vips(interface_name)
+
+ super(HaRouter, self).external_gateway_removed(ex_gw_port,
+ interface_name)
LOG = logging.getLogger(__name__)
INTERNAL_DEV_PREFIX = namespaces.INTERNAL_DEV_PREFIX
+EXTERNAL_DEV_PREFIX = namespaces.EXTERNAL_DEV_PREFIX
class RouterInfo(object):
def get_internal_device_name(self, port_id):
return (INTERNAL_DEV_PREFIX + port_id)[:self.driver.DEV_NAME_LEN]
+ def get_external_device_name(self, port_id):
+ return (EXTERNAL_DEV_PREFIX + port_id)[:self.driver.DEV_NAME_LEN]
+
+ def get_external_device_interface_name(self, ex_gw_port):
+ return self.get_external_device_name(ex_gw_port['id'])
+
def _set_subnet_info(self, port):
ips = port['fixed_ips']
if not ips:
def perform_snat_action(self, snat_callback, *args):
# Process SNAT rules for attached subnets
if self._snat_action:
- snat_callback(self, self._router.get('gw_port'),
- *args, action=self._snat_action)
+ snat_callback(self._router.get('gw_port'),
+ *args,
+ action=self._snat_action)
self._snat_action = None
def _update_routing_table(self, operation, route):
existing_devices = self._get_existing_devices()
current_internal_devs = set(n for n in existing_devices
- if n.startswith(
- INTERNAL_DEV_PREFIX))
+ if n.startswith(INTERNAL_DEV_PREFIX))
current_port_devs = set(self.get_internal_device_name(port_id)
for port_id in current_port_ids)
stale_devs = current_internal_devs - current_port_devs
self.driver.unplug(stale_dev,
namespace=self.ns_name,
prefix=INTERNAL_DEV_PREFIX)
+
+ def _list_floating_ip_cidrs(self):
+ # Compute a list of addresses this router is supposed to have.
+ # This avoids unnecessarily removing those addresses and
+ # causing a momentarily network outage.
+ floating_ips = self.get_floating_ips()
+ return [common_utils.ip_to_cidr(ip['floating_ip_address'])
+ for ip in floating_ips]
+
+ def _plug_external_gateway(self, ex_gw_port, interface_name, ns_name):
+ if not ip_lib.device_exists(interface_name, namespace=ns_name):
+ self.driver.plug(ex_gw_port['network_id'],
+ ex_gw_port['id'],
+ interface_name,
+ ex_gw_port['mac_address'],
+ bridge=self.agent_conf.external_network_bridge,
+ namespace=ns_name,
+ prefix=EXTERNAL_DEV_PREFIX)
+
+ def _external_gateway_added(self, ex_gw_port, interface_name,
+ ns_name, preserve_ips):
+ self._plug_external_gateway(ex_gw_port, interface_name, ns_name)
+
+ self.driver.init_l3(interface_name,
+ [ex_gw_port['ip_cidr']],
+ namespace=ns_name,
+ gateway=ex_gw_port['subnet'].get('gateway_ip'),
+ extra_subnets=ex_gw_port.get('extra_subnets', []),
+ preserve_ips=preserve_ips)
+ ip_address = ex_gw_port['ip_cidr'].split('/')[0]
+ ip_lib.send_gratuitous_arp(ns_name,
+ interface_name,
+ ip_address,
+ self.agent_conf.send_arp_for_ha)
+
+ def external_gateway_added(self, ex_gw_port, interface_name):
+ preserve_ips = self._list_floating_ip_cidrs()
+ self._external_gateway_added(
+ ex_gw_port, interface_name, self.ns_name, preserve_ips)
+
+ def external_gateway_updated(self, ex_gw_port, interface_name):
+ preserve_ips = self._list_floating_ip_cidrs()
+ self._external_gateway_added(
+ ex_gw_port, interface_name, self.ns_name, preserve_ips)
+
+ def external_gateway_removed(self, ex_gw_port, interface_name):
+ self.driver.unplug(interface_name,
+ bridge=self.agent_conf.external_network_bridge,
+ namespace=self.ns_name,
+ prefix=EXTERNAL_DEV_PREFIX)
+
+ def _process_external_gateway(self, ex_gw_port):
+ # TODO(Carl) Refactor to clarify roles of ex_gw_port vs self.ex_gw_port
+ ex_gw_port_id = (ex_gw_port and ex_gw_port['id'] or
+ self.ex_gw_port and self.ex_gw_port['id'])
+
+ interface_name = None
+ if ex_gw_port_id:
+ interface_name = self.get_external_device_name(ex_gw_port_id)
+ if ex_gw_port:
+ def _gateway_ports_equal(port1, port2):
+ def _get_filtered_dict(d, ignore):
+ return dict((k, v) for k, v in d.iteritems()
+ if k not in ignore)
+
+ keys_to_ignore = set(['binding:host_id'])
+ port1_filtered = _get_filtered_dict(port1, keys_to_ignore)
+ port2_filtered = _get_filtered_dict(port2, keys_to_ignore)
+ return port1_filtered == port2_filtered
+
+ self._set_subnet_info(ex_gw_port)
+ if not self.ex_gw_port:
+ self.external_gateway_added(ex_gw_port, interface_name)
+ elif not _gateway_ports_equal(ex_gw_port, self.ex_gw_port):
+ self.external_gateway_updated(ex_gw_port, interface_name)
+ elif not ex_gw_port and self.ex_gw_port:
+ self.external_gateway_removed(self.ex_gw_port, interface_name)
+
+ existing_devices = self._get_existing_devices()
+ stale_devs = [dev for dev in existing_devices
+ if dev.startswith(EXTERNAL_DEV_PREFIX)
+ and dev != interface_name]
+ for stale_dev in stale_devs:
+ LOG.debug('Deleting stale external router device: %s', stale_dev)
+ self.driver.unplug(stale_dev,
+ bridge=self.agent_conf.external_network_bridge,
+ namespace=self.ns_name,
+ prefix=EXTERNAL_DEV_PREFIX)
+
+ # Process SNAT rules for external gateway
+ self.perform_snat_action(self._handle_router_snat_rules,
+ interface_name)
+
+ def external_gateway_nat_rules(self, ex_gw_ip, interface_name):
+ rules = [('POSTROUTING', '! -i %(interface_name)s '
+ '! -o %(interface_name)s -m conntrack ! '
+ '--ctstate DNAT -j ACCEPT' %
+ {'interface_name': interface_name}),
+ ('snat', '-o %s -j SNAT --to-source %s' %
+ (interface_name, ex_gw_ip))]
+ return rules
+
+ def _empty_snat_chains(self, iptables_manager):
+ iptables_manager.ipv4['nat'].empty_chain('POSTROUTING')
+ iptables_manager.ipv4['nat'].empty_chain('snat')
+
+ def _add_snat_rules(self, ex_gw_port, iptables_manager,
+ interface_name, action):
+ if action == 'add_rules' and ex_gw_port:
+ # ex_gw_port should not be None in this case
+ # NAT rules are added only if ex_gw_port has an IPv4 address
+ for ip_addr in ex_gw_port['fixed_ips']:
+ ex_gw_ip = ip_addr['ip_address']
+ if netaddr.IPAddress(ex_gw_ip).version == 4:
+ rules = self.external_gateway_nat_rules(ex_gw_ip,
+ interface_name)
+ for rule in rules:
+ iptables_manager.ipv4['nat'].add_rule(*rule)
+ break
+
+ def _handle_router_snat_rules(self, ex_gw_port,
+ interface_name, action):
+ self._empty_snat_chains(self.iptables_manager)
+
+ self.iptables_manager.ipv4['nat'].add_rule('snat', '-j $float-snat')
+
+ self._add_snat_rules(ex_gw_port,
+ self.iptables_manager,
+ interface_name,
+ action)
+
+ def process_external(self, agent):
+ existing_floating_ips = self.floating_ips
+ try:
+ with self.iptables_manager.defer_apply():
+ ex_gw_port = self.get_ex_gw_port()
+ self._process_external_gateway(ex_gw_port)
+ # TODO(Carl) Return after setting existing_floating_ips and
+ # still call update_fip_statuses?
+ if not ex_gw_port:
+ return
+
+ # Process SNAT/DNAT rules and addresses for floating IPs
+ if self.router['distributed']:
+ self.create_dvr_fip_interfaces(ex_gw_port)
+ self.process_snat_dnat_for_fip()
+
+ # Once NAT rules for floating IPs are safely in place
+ # configure their addresses on the external gateway port
+ interface_name = self.get_external_device_interface_name(
+ ex_gw_port)
+ fip_statuses = self.configure_fip_addresses(interface_name)
+
+ except (n_exc.FloatingIpSetupException,
+ n_exc.IpTablesApplyException) as e:
+ # All floating IPs must be put in error state
+ LOG.exception(e)
+ fip_statuses = self.put_fips_in_error_state()
+
+ agent.update_fip_statuses(self, existing_floating_ips, fip_statuses)
external_port = router.get_ex_gw_port()
ex_port_ipv6 = router._get_ipv6_lladdr(
external_port['mac_address'])
- external_device_name = self.agent.get_external_device_name(
+ external_device_name = router.get_external_device_name(
external_port['id'])
external_device_cidr = external_port['ip_cidr']
internal_port = router.router[l3_constants.INTERFACE_KEY][0]
floating_ips = router.router[l3_constants.FLOATINGIP_KEY]
external_port = router.get_ex_gw_port()
return len(floating_ips) and all(ip_lib.device_exists_with_ip_mac(
- self.agent.get_external_device_name(external_port['id']),
+ router.get_external_device_name(external_port['id']),
'%s/32' % fip['floating_ip_address'],
external_port['mac_address'],
namespace=router.ns_name) for fip in floating_ips)
self.assertNotIn(old_gw, new_config)
self.assertIn(new_gw, new_config)
external_port = router.get_ex_gw_port()
- external_device_name = self.agent.get_external_device_name(
+ external_device_name = router.get_external_device_name(
external_port['id'])
self.assertNotIn('%s/24 dev %s' %
(old_external_device_ip, external_device_name),
if enable_ha:
port = router.get_ex_gw_port()
- interface_name = self.agent.get_external_device_name(port['id'])
+ interface_name = router.get_external_device_name(port['id'])
self._assert_no_ip_addresses_on_interface(router.ns_name,
interface_name)
utils.wait_until_true(lambda: router.ha_state == 'master')
def _assert_external_device(self, router):
external_port = router.get_ex_gw_port()
self.assertTrue(self.device_exists_with_ip_mac(
- external_port, self.agent.get_external_device_name,
+ external_port, router.get_external_device_name,
router.ns_name))
def _assert_gateway(self, router):
external_port = router.get_ex_gw_port()
- external_device_name = self.agent.get_external_device_name(
+ external_device_name = router.get_external_device_name(
external_port['id'])
external_device = ip_lib.IPDevice(external_device_name,
namespace=router.ns_name)
# snat_ns_name namespace
if self.agent.conf.agent_mode == 'dvr_snat':
self.assertTrue(self.device_exists_with_ip_mac(
- external_port, self.agent.get_external_device_name,
+ external_port, router.get_external_device_name,
snat_ns_name))
# if the agent is in dvr mode then the snat_ns_name namespace
# should not be present at all:
namespace = dvr_snat_ns.SnatNamespace.get_snat_ns_name(
router.router_id)
external_port = router.get_ex_gw_port()
- external_device_name = self.agent.get_external_device_name(
+ external_device_name = router.get_external_device_name(
external_port['id'])
external_device = ip_lib.IPDevice(external_device_name,
namespace=namespace)
ri._set_subnet_info = mock.Mock()
ri._set_subnet_arp_info = mock.Mock()
ri._internal_network_added = mock.Mock()
+ ri._set_subnet_arp_info = mock.Mock()
ri.internal_network_added(port)
self.assertEqual(ri._snat_redirect_add.call_count, 1)
self.assertEqual(ri._set_subnet_info.call_count, 1)
if router.get('distributed'):
agent.conf.agent_mode = 'dvr_snat'
agent.host = HOSTNAME
- agent._create_dvr_gateway = mock.Mock()
ri = dvr_router.DvrRouter(agent,
HOSTNAME,
router['id'],
router,
**self.ri_kwargs)
+ ri._create_dvr_gateway = mock.Mock()
ri.get_snat_interfaces = mock.Mock(return_value=self.snat_ports)
ri.create_snat_namespace()
ri.fip_ns = agent.get_fip_ns(ex_net_id)
'network_id': ex_net_id,
'mac_address': 'ca:fe:de:ad:be:ef',
'ip_cidr': '20.0.0.30/24'}
- interface_name = agent.get_external_device_name(ex_gw_port['id'])
+ interface_name = ri.get_external_device_name(ex_gw_port['id'])
if action == 'add':
self.device_exists.return_value = False
'fixed_ip_address': '192.168.0.1',
'port_id': _uuid()}]}
router[l3_constants.FLOATINGIP_KEY] = fake_fip['floatingips']
- agent.external_gateway_added(ri, ex_gw_port, interface_name)
+ ri.external_gateway_added(ex_gw_port, interface_name)
if not router.get('distributed'):
self.assertEqual(self.mock_driver.plug.call_count, 1)
self.assertEqual(self.mock_driver.init_l3.call_count, 1)
['20.0.0.30/24'],
**kwargs)
else:
- agent._create_dvr_gateway.assert_called_once_with(
- ri, ex_gw_port, interface_name,
+ ri._create_dvr_gateway.assert_called_once_with(
+ ex_gw_port, interface_name,
self.snat_ports)
elif action == 'remove':
self.device_exists.return_value = True
- agent._map_internal_interfaces = mock.Mock(return_value=sn_port)
+ ri._map_internal_interfaces = mock.Mock(return_value=sn_port)
ri._snat_redirect_remove = mock.Mock()
- agent.external_gateway_removed(ri, ex_gw_port, interface_name)
+ ri.external_gateway_removed(ex_gw_port, interface_name)
if not router.get('distributed'):
self.mock_driver.unplug.assert_called_once_with(
interface_name,
else:
raise Exception("Invalid action %s" % action)
- def _prepare_ext_gw_test(self, agent):
+ def _prepare_ext_gw_test(self, ri):
ex_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30',
'subnet_id': _uuid()}],
'subnet': {'gateway_ip': '20.0.0.1'},
'network_id': _uuid(),
'mac_address': 'ca:fe:de:ad:be:ef',
'ip_cidr': '20.0.0.30/24'}
- interface_name = agent.get_external_device_name(ex_gw_port['id'])
+ interface_name = ri.get_external_device_name(ex_gw_port['id'])
self.device_exists.return_value = True
def test_external_gateway_updated(self):
router = prepare_router_data(num_internal_ports=2)
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
- interface_name, ex_gw_port = self._prepare_ext_gw_test(agent)
+ interface_name, ex_gw_port = self._prepare_ext_gw_test(ri)
fake_fip = {'floatingips': [{'id': _uuid(),
'floating_ip_address': '192.168.1.34',
'fixed_ip_address': '192.168.0.1',
'port_id': _uuid()}]}
router[l3_constants.FLOATINGIP_KEY] = fake_fip['floatingips']
- agent.external_gateway_updated(ri, ex_gw_port,
- interface_name)
+ ri.external_gateway_updated(ex_gw_port, interface_name)
self.assertEqual(self.mock_driver.plug.call_count, 0)
self.assertEqual(self.mock_driver.init_l3.call_count, 1)
self.send_arp.assert_called_once_with(ri.ns_name, interface_name,
router,
**self.ri_kwargs)
ri.create_snat_namespace()
- interface_name, ex_gw_port = self._prepare_ext_gw_test(agent)
- agent._external_gateway_added = mock.Mock()
+ interface_name, ex_gw_port = self._prepare_ext_gw_test(ri)
+ ri._external_gateway_added = mock.Mock()
# test agent mode = dvr (compute node)
- router['distributed'] = True
router['gw_port_host'] = host
agent.conf.agent_mode = agent_mode
- agent.external_gateway_updated(ri, ex_gw_port,
- interface_name)
+ ri.external_gateway_updated(ex_gw_port, interface_name)
# no gateway should be added on dvr node
self.assertEqual(expected_call_count,
- agent._external_gateway_added.call_count)
+ ri._external_gateway_added.call_count)
def test_ext_gw_updated_dvr_agent_mode(self):
# no gateway should be added on dvr node
def test_ext_gw_updated_dvr_snat_agent_mode_host(self):
# gateway should be added on dvr_snat node
- self._test_ext_gw_updated_dvr_agent_mode(self.conf.host,
+ self._test_ext_gw_updated_dvr_agent_mode(HOSTNAME,
'dvr_snat', 1)
def test_agent_add_external_gateway(self):
router = ri.router
agent.host = HOSTNAME
fake_fip_id = 'fake_fip_id'
- agent.create_dvr_fip_interfaces = mock.Mock()
+ ri.create_dvr_fip_interfaces = mock.Mock()
ri.process_floating_ip_addresses = mock.Mock()
ri.process_floating_ip_nat_rules = mock.Mock()
ri.process_floating_ip_addresses.return_value = {
fake_fip_id: 'ACTIVE'}
- agent.external_gateway_added = mock.Mock()
- agent.external_gateway_updated = mock.Mock()
+ ri.external_gateway_added = mock.Mock()
+ ri.external_gateway_updated = mock.Mock()
fake_floatingips1 = {'floatingips': [
{'id': fake_fip_id,
'floating_ip_address': '8.8.8.8',
ri.process_floating_ip_addresses.reset_mock()
ri.process_floating_ip_nat_rules.assert_called_with()
ri.process_floating_ip_nat_rules.reset_mock()
- agent.external_gateway_added.reset_mock()
+ ri.external_gateway_added.reset_mock()
# remap floating IP to a new fixed ip
fake_floatingips2 = copy.deepcopy(fake_floatingips1)
ri.process_floating_ip_addresses.reset_mock()
ri.process_floating_ip_nat_rules.assert_called_with()
ri.process_floating_ip_nat_rules.reset_mock()
- self.assertEqual(agent.external_gateway_added.call_count, 0)
- self.assertEqual(agent.external_gateway_updated.call_count, 0)
- agent.external_gateway_added.reset_mock()
- agent.external_gateway_updated.reset_mock()
+ self.assertEqual(ri.external_gateway_added.call_count, 0)
+ self.assertEqual(ri.external_gateway_updated.call_count, 0)
+ ri.external_gateway_added.reset_mock()
+ ri.external_gateway_updated.reset_mock()
# change the ex_gw_port a bit to test gateway update
new_gw_port = copy.deepcopy(ri.router['gw_port'])
agent.process_router(ri)
ri.process_floating_ip_addresses.reset_mock()
ri.process_floating_ip_nat_rules.reset_mock()
- self.assertEqual(agent.external_gateway_added.call_count, 0)
- self.assertEqual(agent.external_gateway_updated.call_count, 1)
+ self.assertEqual(ri.external_gateway_added.call_count, 0)
+ self.assertEqual(ri.external_gateway_updated.call_count, 1)
# remove just the floating ips
del router[l3_constants.FLOATINGIP_KEY]
with mock.patch.object(lla.LinkLocalAllocator, '_write'):
if ri.router['distributed']:
ri.fip_ns = agent.get_fip_ns(ex_gw_port['network_id'])
- agent.create_dvr_fip_interfaces(ri, ex_gw_port)
+ ri.create_dvr_fip_interfaces(ex_gw_port)
fip_statuses = ri.process_floating_ip_addresses(
mock.sentinel.interface_name)
self.assertEqual({fip_id: l3_constants.FLOATINGIP_STATUS_ACTIVE},
sub_info):
fips.return_value = fake_floatingips
fip_gw_port.return_value = agent_gateway_port[0]
- agent.create_dvr_fip_interfaces(ri, ext_gw_port)
+ ri.create_dvr_fip_interfaces(ext_gw_port)
self.assertTrue(fip_gw_port.called)
self.assertTrue(fips.called)
self.assertEqual(ri.fip_ns.agent_gateway_port,
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
ri.iptables_manager.ipv4['nat'] = mock.MagicMock()
- agent.get_external_device_name = mock.Mock(return_value='exgw')
+ ri.get_external_device_name = mock.Mock(return_value='exgw')
self._test_process_floating_ip_addresses_add(ri, agent)
def test_process_router_dist_floating_ip_add(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
router = prepare_router_data(enable_snat=True)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
- agent.external_gateway_added = mock.Mock()
+ ri.external_gateway_added = mock.Mock()
# Process with NAT
agent.process_router(ri)
orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
router = prepare_router_data(enable_snat=False)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
- agent.external_gateway_added = mock.Mock()
+ ri.external_gateway_added = mock.Mock()
# Process without NAT
agent.process_router(ri)
orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
router = prepare_router_data()
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
- agent.external_gateway_added = mock.Mock()
+ ri.external_gateway_added = mock.Mock()
# Process with NAT
agent.process_router(ri)
# Add an interface and reprocess
gw_port = router['gw_port']
router['gw_port'] = None
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
- agent.external_gateway_added = mock.Mock()
+ ri.external_gateway_added = mock.Mock()
self._process_router_instance_for_agent(agent, ri, router)
orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
router['gw_port'] = gw_port
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
with mock.patch.object(
- agent,
+ ri,
'external_gateway_nat_rules') as external_gateway_nat_rules:
self._process_router_instance_for_agent(agent, ri, router)
new_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
self, router, ra_mode=None, addr_mode=None):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
- agent.external_gateway_added = mock.Mock()
+ ri.external_gateway_added = mock.Mock()
# Process with NAT
agent.process_router(ri)
orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
router = prepare_router_data()
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
- agent.external_gateway_added = mock.Mock()
+ ri.external_gateway_added = mock.Mock()
# Process with NAT
agent.process_router(ri)
# Add an IPv4 and IPv6 interface and reprocess
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
router = prepare_router_data(num_internal_ports=2)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
- agent.external_gateway_added = mock.Mock()
+ ri.external_gateway_added = mock.Mock()
# Process with NAT
agent.process_router(ri)
# Add an interface and reprocess
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
router = prepare_router_data()
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
- agent.external_gateway_added = mock.Mock()
+ ri.external_gateway_added = mock.Mock()
self._process_router_instance_for_agent(agent, ri, router)
# Add an IPv6 interface and reprocess
router_append_interface(router, count=1, ip_version=6)
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
router = prepare_router_data()
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
- agent.external_gateway_added = mock.Mock()
+ ri.external_gateway_added = mock.Mock()
with mock.patch.object(
ri,
'internal_network_added') as internal_network_added:
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
router = prepare_router_data()
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
- agent.external_gateway_added = mock.Mock()
+ ri.external_gateway_added = mock.Mock()
# add an internal port
agent.process_router(ri)
ri = legacy_router.LegacyRouter(router['id'],
router,
**self.ri_kwargs)
- agent.external_gateway_added = mock.Mock()
+ ri.external_gateway_added = mock.Mock()
agent.process_router(ri)
# Assess the call for putting the floating IP up was performed
mock_update_fip_status.assert_called_once_with(
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
ri.process_floating_ip_addresses = mock.Mock(
side_effect=RuntimeError)
- agent.external_gateway_added = mock.Mock()
+ ri.external_gateway_added = mock.Mock()
agent.process_router(ri)
# Assess the call for putting the floating IP into Error
# was performed
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
ri.iptables_manager._apply = mock.Mock(side_effect=Exception)
- agent._process_external(ri)
+ ri.process_external(agent)
# Assess the call for putting the floating IP into Error
# was performed
mock_update_fip_status.assert_called_once_with(
agent,
HOSTNAME,
'foo_router_id',
- {'distributed': True},
+ {},
**self.ri_kwargs)
ri.iptables_manager = mock.Mock()
- with mock.patch.object(l3_agent.LOG, 'debug') as log_debug:
- agent._handle_router_snat_rules(
- ri, mock.ANY, mock.ANY, mock.ANY)
+ with mock.patch.object(dvr_router.LOG, 'debug') as log_debug:
+ ri._handle_router_snat_rules(mock.ANY, mock.ANY, mock.ANY)
self.assertIsNone(ri.snat_iptables_manager)
self.assertFalse(ri.iptables_manager.called)
self.assertTrue(log_debug.called)
def test_handle_router_snat_rules_add_back_jump(self):
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- ri = mock.MagicMock()
+ ri = l3router.RouterInfo(_uuid(), {}, **self.ri_kwargs)
+ ri.iptables_manager = mock.MagicMock()
port = {'fixed_ips': [{'ip_address': '192.168.1.4'}]}
- ri.router = {'distributed': False}
- agent._handle_router_snat_rules(ri, port, "iface", "add_rules")
+ ri._handle_router_snat_rules(port, "iface", "add_rules")
nat = ri.iptables_manager.ipv4['nat']
nat.empty_chain.assert_any_call('snat')
break
def test_handle_router_snat_rules_add_rules(self):
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
ri = l3router.RouterInfo(_uuid(), {}, **self.ri_kwargs)
ex_gw_port = {'fixed_ips': [{'ip_address': '192.168.1.4'}]}
ri.router = {'distributed': False}
- agent._handle_router_snat_rules(ri, ex_gw_port,
- "iface", "add_rules")
+ ri._handle_router_snat_rules(ex_gw_port, "iface", "add_rules")
nat_rules = map(str, ri.iptables_manager.ipv4['nat'].rules)
wrap_name = ri.iptables_manager.wrap_name
'internal_network_removed'),
mock.patch.object(ri,
'internal_network_added'),
- mock.patch.object(l3_agent.L3NATAgent,
+ mock.patch.object(ri,
'external_gateway_removed'),
- mock.patch.object(l3_agent.L3NATAgent,
+ mock.patch.object(ri,
'external_gateway_added')
) as (internal_network_removed,
internal_network_added,
interface_name = ri.get_snat_int_device_name(port_id)
self.device_exists.return_value = False
- agent._create_dvr_gateway(ri, dvr_gw_port, interface_name,
- self.snat_ports)
+ ri._create_dvr_gateway(dvr_gw_port, interface_name, self.snat_ports)
# check 2 internal ports are plugged
# check 1 ext-gw-port is plugged
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
agent.conf.agent_mode = 'dvr_snat'
router = prepare_router_data(num_internal_ports=2)
- router['distributed'] = True
router['gw_port_host'] = HOSTNAME
self.mock_driver.unplug.reset_mock()
self.device_exists.return_value = True
fip_ns = ri.fip_ns
- agent.external_gateway_removed(
- ri, ri.ex_gw_port,
- agent.get_external_device_name(ri.ex_gw_port['id']))
+ ri.snat_namespace = mock.Mock()
+ ri.external_gateway_removed(
+ ri.ex_gw_port,
+ ri.get_external_device_name(ri.ex_gw_port['id']))
if fip_ns:
ri.remove_floating_ip.assert_called_once_with(self.mock_ip_dev,