from oslo_utils import timeutils
from neutron.agent.l3 import dvr
-from neutron.agent.l3 import dvr_router
+from neutron.agent.l3 import dvr_edge_router as dvr_router
+from neutron.agent.l3 import dvr_local_router as dvr_local_router
from neutron.agent.l3 import ha
from neutron.agent.l3 import ha_router
from neutron.agent.l3 import legacy_router
if router.get('distributed'):
kwargs['agent'] = self
kwargs['host'] = self.host
- return dvr_router.DvrRouter(*args, **kwargs)
+ if self.conf.agent_mode == l3_constants.L3_AGENT_MODE_DVR_SNAT:
+ return dvr_router.DvrEdgeRouter(*args, **kwargs)
+ else:
+ return dvr_local_router.DvrLocalRouter(*args, **kwargs)
if router.get('ha'):
kwargs['state_change_callback'] = self.enqueue_state_change
--- /dev/null
+# Copyright (c) 2015 Openstack Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from oslo_log import log as logging
+
+from neutron.agent.l3 import dvr_local_router
+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
+
+LOG = logging.getLogger(__name__)
+
+
+class DvrEdgeRouter(dvr_local_router.DvrLocalRouter):
+
+ def __init__(self, agent, host, *args, **kwargs):
+ super(DvrEdgeRouter, self).__init__(agent, host, *args, **kwargs)
+ self.snat_namespace = None
+
+ def external_gateway_added(self, ex_gw_port, interface_name):
+ super(DvrEdgeRouter, self).external_gateway_added(
+ ex_gw_port, interface_name)
+ if self._is_this_snat_host():
+ snat_ports = self.get_snat_interfaces()
+ self._create_dvr_gateway(ex_gw_port, interface_name, snat_ports)
+
+ 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):
+ super(DvrEdgeRouter, self).external_gateway_removed(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.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 internal_network_added(self, port):
+ super(DvrEdgeRouter, self).internal_network_added(port)
+
+ # TODO(gsagie) some of this checks are already implemented
+ # in the base class, think how to avoid re-doing them
+ if not self._is_this_snat_host():
+ return
+
+ snat_ports = self.get_snat_interfaces()
+ sn_port = self._map_internal_interfaces(port, snat_ports)
+ if not sn_port:
+ return
+
+ ns_name = dvr_snat_ns.SnatNamespace.get_snat_ns_name(self.router['id'])
+ interface_name = self.get_snat_int_device_name(sn_port['id'])
+ self._internal_network_added(
+ ns_name,
+ sn_port['network_id'],
+ sn_port['id'],
+ sn_port['fixed_ips'],
+ sn_port['mac_address'],
+ interface_name,
+ dvr_snat_ns.SNAT_INT_DEV_PREFIX)
+
+ def _dvr_internal_network_removed(self, port):
+ super(DvrEdgeRouter, self)._dvr_internal_network_removed(port)
+
+ if not self.ex_gw_port:
+ return
+
+ sn_port = self._map_internal_interfaces(port, self.snat_ports)
+ if not sn_port:
+ return
+
+ is_this_snat_host = ('binding:host_id' in self.ex_gw_port) and (
+ self.ex_gw_port['binding:host_id'] == self.host)
+ if not is_this_snat_host:
+ return
+
+ snat_interface = self.get_snat_int_device_name(sn_port['id'])
+ ns_name = self.snat_namespace.name
+ prefix = dvr_snat_ns.SNAT_INT_DEV_PREFIX
+ if ip_lib.device_exists(snat_interface, namespace=ns_name):
+ self.driver.unplug(snat_interface, namespace=ns_name,
+ prefix=prefix)
+
+ 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
+ interface_name = self.get_snat_int_device_name(port['id'])
+ self._internal_network_added(
+ snat_ns.name, port['network_id'],
+ port['id'], port['fixed_ips'],
+ 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 create_snat_namespace(self):
+ # TODO(mlavalle): in the near future, this method should contain the
+ # code in the L3 agent that creates a gateway for a dvr. The first step
+ # is to move the creation of the snat namespace here
+ self.snat_namespace = dvr_snat_ns.SnatNamespace(self.router['id'],
+ self.agent_conf,
+ self.driver,
+ self.use_ipv6)
+ self.snat_namespace.create()
+ return self.snat_namespace
+
+ def get_snat_int_device_name(self, port_id):
+ long_name = dvr_snat_ns.SNAT_INT_DEV_PREFIX + port_id
+ return long_name[:self.driver.DEV_NAME_LEN]
+
+ def _is_this_snat_host(self):
+ return self.get_gw_port_host() == self.host
from oslo_utils import excutils
from neutron.agent.l3 import dvr_fip_ns
-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 exceptions
from neutron.common import utils as common_utils
MASK_30 = 0x3fffffff
-class DvrRouter(router.RouterInfo):
+class DvrLocalRouter(router.RouterInfo):
def __init__(self, agent, host, *args, **kwargs):
- super(DvrRouter, self).__init__(*args, **kwargs)
+ super(DvrLocalRouter, self).__init__(*args, **kwargs)
self.agent = agent
self.host = host
# Linklocal subnet for router and floating IP namespace link
self.rtr_fip_subnet = None
self.dist_fip_count = None
- self.snat_namespace = None
self.fip_ns = None
def get_floating_ips(self):
"""Filter Floating IPs to be hosted on this agent."""
- floating_ips = super(DvrRouter, self).get_floating_ips()
+ floating_ips = super(DvrLocalRouter, self).get_floating_ips()
return [i for i in floating_ips if i['host'] == self.host]
def get_snat_interfaces(self):
return self.router.get(l3_constants.SNAT_ROUTER_INTF_KEY, [])
- def get_snat_int_device_name(self, port_id):
- long_name = dvr_snat_ns.SNAT_INT_DEV_PREFIX + port_id
- return long_name[:self.driver.DEV_NAME_LEN]
-
def _handle_fip_nat_rules(self, interface_name, action):
"""Configures NAT rules for Floating IPs for DVR.
return l3_constants.FLOATINGIP_STATUS_ACTIVE
def remove_floating_ip(self, device, ip_cidr):
- super(DvrRouter, self).remove_floating_ip(device, ip_cidr)
+ super(DvrLocalRouter, self).remove_floating_ip(device, ip_cidr)
self.floating_ip_removed_dist(ip_cidr)
- def create_snat_namespace(self):
- # TODO(mlavalle): in the near future, this method should contain the
- # code in the L3 agent that creates a gateway for a dvr. The first step
- # is to move the creation of the snat namespace here
- self.snat_namespace = dvr_snat_ns.SnatNamespace(self.router['id'],
- self.agent_conf,
- self.driver,
- self.use_ipv6)
- self.snat_namespace.create()
- return self.snat_namespace
-
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)
+ super(DvrLocalRouter, self).internal_network_added(port)
# NOTE: The following function _set_subnet_arp_info
# should be called to dynamically populate the arp
interface_name = self.get_internal_device_name(port['id'])
self._snat_redirect_add(sn_port, port, interface_name)
- if not self._is_this_snat_host():
- return
-
- ns_name = dvr_snat_ns.SnatNamespace.get_snat_ns_name(self.router['id'])
- interface_name = self.get_snat_int_device_name(sn_port['id'])
- self._internal_network_added(
- ns_name,
- sn_port['network_id'],
- sn_port['id'],
- sn_port['fixed_ips'],
- sn_port['mac_address'],
- interface_name,
- dvr_snat_ns.SNAT_INT_DEV_PREFIX)
-
def _dvr_internal_network_removed(self, port):
if not self.ex_gw_port:
return
interface_name = self.get_internal_device_name(port['id'])
self._snat_redirect_remove(sn_port, port, interface_name)
- 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
-
- snat_interface = (
- self.get_snat_int_device_name(sn_port['id']))
- ns_name = self.snat_namespace.name
- prefix = dvr_snat_ns.SNAT_INT_DEV_PREFIX
- if ip_lib.device_exists(snat_interface, namespace=ns_name):
- self.driver.unplug(snat_interface, namespace=ns_name,
- prefix=prefix)
-
def internal_network_removed(self, port):
self._dvr_internal_network_removed(port)
- super(DvrRouter, self).internal_network_removed(port)
+ super(DvrLocalRouter, self).internal_network_removed(port)
def get_floating_agent_gw_interface(self, ext_net_id):
"""Filter Floating Agent GW port for the external network."""
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
- interface_name = self.get_snat_int_device_name(port['id'])
- self._internal_network_added(snat_ns.name, port['network_id'],
- port['id'], port['fixed_ips'],
- 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,
if gateway:
self._snat_redirect_add(gateway, 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'],
'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=[])
+ pass
def external_gateway_removed(self, ex_gw_port, interface_name):
# TODO(Carl) Should this be calling process_snat_dnat_for_fip?
internal_interface = self.get_internal_device_name(p['id'])
self._snat_redirect_remove(gateway, 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:
if self.get_gw_port_host() != self.host:
return
- super(DvrRouter, self).perform_snat_action(snat_callback, *args)
+ super(DvrLocalRouter,
+ self).perform_snat_action(snat_callback, *args)
def process_external(self, agent):
ex_gw_port = self.get_ex_gw_port()
if ex_gw_port:
self.create_dvr_fip_interfaces(ex_gw_port)
- super(DvrRouter, self).process_external(agent)
+ super(DvrLocalRouter, self).process_external(agent)
def create_dvr_fip_interfaces(self, ex_gw_port):
floating_ips = self.get_floating_ips()
self.fip_ns = agent.get_fip_ns(ex_gw_port['network_id'])
self.fip_ns.scan_fip_ports(self)
- super(DvrRouter, self).process(agent)
+ super(DvrLocalRouter, self).process(agent)
--- /dev/null
+# Copyright (c) 2015 Openstack Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import copy
+import netaddr
+from six import moves
+
+from neutron.common import constants as l3_constants
+from neutron.openstack.common import uuidutils
+
+_uuid = uuidutils.generate_uuid
+
+
+class FakeDev(object):
+ def __init__(self, name):
+ self.name = name
+
+
+def get_ha_interface(ip='169.254.192.1', mac='12:34:56:78:2b:5d'):
+ subnet_id = _uuid()
+ return {'admin_state_up': True,
+ 'device_id': _uuid(),
+ 'device_owner': 'network:router_ha_interface',
+ 'fixed_ips': [{'ip_address': ip,
+ 'prefixlen': 18,
+ 'subnet_id': subnet_id}],
+ 'id': _uuid(),
+ 'mac_address': mac,
+ 'name': u'L3 HA Admin port 0',
+ 'network_id': _uuid(),
+ 'status': u'ACTIVE',
+ 'subnets': [{'cidr': '169.254.192.0/18',
+ 'gateway_ip': '169.254.255.254',
+ 'id': subnet_id}],
+ 'tenant_id': '',
+ 'agent_id': _uuid(),
+ 'agent_host': 'aaa',
+ 'priority': 1}
+
+
+def prepare_router_data(ip_version=4, enable_snat=None, num_internal_ports=1,
+ enable_floating_ip=False, enable_ha=False,
+ extra_routes=False, dual_stack=False,
+ v6_ext_gw_with_sub=True, **kwargs):
+ fixed_ips = []
+ subnets = []
+ gateway_mac = kwargs.get('gateway_mac', 'ca:fe:de:ad:be:ee')
+ for loop_version in (4, 6):
+ if loop_version == 4 and (ip_version == 4 or dual_stack):
+ ip_address = kwargs.get('ip_address', '19.4.4.4')
+ prefixlen = 24
+ subnet_cidr = kwargs.get('subnet_cidr', '19.4.4.0/24')
+ gateway_ip = kwargs.get('gateway_ip', '19.4.4.1')
+ elif (loop_version == 6 and (ip_version == 6 or dual_stack) and
+ v6_ext_gw_with_sub):
+ ip_address = kwargs.get('ip_address', 'fd00::4')
+ prefixlen = 64
+ subnet_cidr = kwargs.get('subnet_cidr', 'fd00::/64')
+ gateway_ip = kwargs.get('gateway_ip', 'fd00::1')
+ else:
+ continue
+ subnet_id = _uuid()
+ fixed_ips.append({'ip_address': ip_address,
+ 'subnet_id': subnet_id,
+ 'prefixlen': prefixlen})
+ subnets.append({'id': subnet_id,
+ 'cidr': subnet_cidr,
+ 'gateway_ip': gateway_ip})
+ if not fixed_ips and v6_ext_gw_with_sub:
+ raise ValueError("Invalid ip_version: %s" % ip_version)
+
+ router_id = _uuid()
+ ex_gw_port = {'id': _uuid(),
+ 'mac_address': gateway_mac,
+ 'network_id': _uuid(),
+ 'fixed_ips': fixed_ips,
+ 'subnets': subnets}
+
+ routes = []
+ if extra_routes:
+ routes = [{'destination': '8.8.8.0/24', 'nexthop': '19.4.4.4'}]
+
+ router = {
+ 'id': router_id,
+ 'distributed': False,
+ l3_constants.INTERFACE_KEY: [],
+ 'routes': routes,
+ 'gw_port': ex_gw_port}
+
+ if enable_floating_ip:
+ router[l3_constants.FLOATINGIP_KEY] = [{
+ 'id': _uuid(),
+ 'port_id': _uuid(),
+ 'status': 'DOWN',
+ 'floating_ip_address': '19.4.4.2',
+ 'fixed_ip_address': '10.0.0.1'}]
+
+ router_append_interface(router, count=num_internal_ports,
+ ip_version=ip_version, dual_stack=dual_stack)
+ if enable_ha:
+ router['ha'] = True
+ router['ha_vr_id'] = 1
+ router[l3_constants.HA_INTERFACE_KEY] = (get_ha_interface())
+
+ if enable_snat is not None:
+ router['enable_snat'] = enable_snat
+ return router
+
+
+def get_subnet_id(port):
+ return port['fixed_ips'][0]['subnet_id']
+
+
+def router_append_interface(router, count=1, ip_version=4, ra_mode=None,
+ addr_mode=None, dual_stack=False):
+ interfaces = router[l3_constants.INTERFACE_KEY]
+ current = sum(
+ [netaddr.IPNetwork(subnet['cidr']).version == ip_version
+ for p in interfaces for subnet in p['subnets']])
+
+ mac_address = netaddr.EUI('ca:fe:de:ad:be:ef')
+ mac_address.dialect = netaddr.mac_unix
+ for i in range(current, current + count):
+ fixed_ips = []
+ subnets = []
+ for loop_version in (4, 6):
+ if loop_version == 4 and (ip_version == 4 or dual_stack):
+ ip_pool = '35.4.%i.4'
+ cidr_pool = '35.4.%i.0/24'
+ prefixlen = 24
+ gw_pool = '35.4.%i.1'
+ elif loop_version == 6 and (ip_version == 6 or dual_stack):
+ ip_pool = 'fd01:%x:1::6'
+ cidr_pool = 'fd01:%x:1::/64'
+ prefixlen = 64
+ gw_pool = 'fd01:%x:1::1'
+ else:
+ continue
+ subnet_id = _uuid()
+ fixed_ips.append({'ip_address': ip_pool % i,
+ 'subnet_id': subnet_id,
+ 'prefixlen': prefixlen})
+ subnets.append({'id': subnet_id,
+ 'cidr': cidr_pool % i,
+ 'gateway_ip': gw_pool % i,
+ 'ipv6_ra_mode': ra_mode,
+ 'ipv6_address_mode': addr_mode})
+ if not fixed_ips:
+ raise ValueError("Invalid ip_version: %s" % ip_version)
+
+ interfaces.append(
+ {'id': _uuid(),
+ 'network_id': _uuid(),
+ 'admin_state_up': True,
+ 'fixed_ips': fixed_ips,
+ 'mac_address': str(mac_address),
+ 'subnets': subnets})
+ mac_address.value += 1
+
+
+def router_append_subnet(router, count=1, ip_version=4,
+ ipv6_subnet_modes=None, interface_id=None):
+ if ip_version == 6:
+ subnet_mode_none = {'ra_mode': None, 'address_mode': None}
+ if not ipv6_subnet_modes:
+ ipv6_subnet_modes = [subnet_mode_none] * count
+ elif len(ipv6_subnet_modes) != count:
+ ipv6_subnet_modes.extend([subnet_mode_none for i in
+ moves.range(len(ipv6_subnet_modes),
+ count)])
+
+ if ip_version == 4:
+ ip_pool = '35.4.%i.4'
+ cidr_pool = '35.4.%i.0/24'
+ prefixlen = 24
+ gw_pool = '35.4.%i.1'
+ elif ip_version == 6:
+ ip_pool = 'fd01:%x::6'
+ cidr_pool = 'fd01:%x::/64'
+ prefixlen = 64
+ gw_pool = 'fd01:%x::1'
+ else:
+ raise ValueError("Invalid ip_version: %s" % ip_version)
+
+ interfaces = copy.deepcopy(router.get(l3_constants.INTERFACE_KEY, []))
+ if interface_id:
+ try:
+ interface = next(i for i in interfaces
+ if i['id'] == interface_id)
+ except StopIteration:
+ raise ValueError("interface_id not found")
+
+ fixed_ips, subnets = interface['fixed_ips'], interface['subnets']
+ else:
+ interface = None
+ fixed_ips, subnets = [], []
+
+ num_existing_subnets = len(subnets)
+ for i in moves.range(count):
+ subnet_id = _uuid()
+ fixed_ips.append(
+ {'ip_address': ip_pool % (i + num_existing_subnets),
+ 'subnet_id': subnet_id,
+ 'prefixlen': prefixlen})
+ subnets.append(
+ {'id': subnet_id,
+ 'cidr': cidr_pool % (i + num_existing_subnets),
+ 'gateway_ip': gw_pool % (i + num_existing_subnets),
+ 'ipv6_ra_mode': ipv6_subnet_modes[i]['ra_mode'],
+ 'ipv6_address_mode': ipv6_subnet_modes[i]['address_mode']})
+
+ if interface:
+ # Update old interface
+ index = interfaces.index(interface)
+ interfaces[index].update({'fixed_ips': fixed_ips, 'subnets': subnets})
+ else:
+ # New interface appended to interfaces list
+ mac_address = netaddr.EUI('ca:fe:de:ad:be:ef')
+ mac_address.dialect = netaddr.mac_unix
+ interfaces.append(
+ {'id': _uuid(),
+ 'network_id': _uuid(),
+ 'admin_state_up': True,
+ 'mac_address': str(mac_address),
+ 'fixed_ips': fixed_ips,
+ 'subnets': subnets})
+
+ router[l3_constants.INTERFACE_KEY] = interfaces
+
+
+def prepare_ext_gw_test(context, ri, dual_stack=False):
+ subnet_id = _uuid()
+ fixed_ips = [{'subnet_id': subnet_id,
+ 'ip_address': '20.0.0.30',
+ 'prefixlen': 24}]
+ subnets = [{'id': subnet_id,
+ 'cidr': '20.0.0.0/24',
+ 'gateway_ip': '20.0.0.1'}]
+ if dual_stack:
+ subnet_id_v6 = _uuid()
+ fixed_ips.append({'subnet_id': subnet_id_v6,
+ 'ip_address': '2001:192:168:100::2',
+ 'prefixlen': 64})
+ subnets.append({'id': subnet_id_v6,
+ 'cidr': '2001:192:168:100::/64',
+ 'gateway_ip': '2001:192:168:100::1'})
+ ex_gw_port = {'fixed_ips': fixed_ips,
+ 'subnets': subnets,
+ 'extra_subnets': [{'cidr': '172.16.0.0/24'}],
+ 'id': _uuid(),
+ 'network_id': _uuid(),
+ 'mac_address': 'ca:fe:de:ad:be:ef'}
+ interface_name = ri.get_external_device_name(ex_gw_port['id'])
+
+ context.device_exists.return_value = True
+
+ return interface_name, ex_gw_port
from neutron.common import constants as l3_constants
from neutron.common import utils as common_utils
from neutron.openstack.common import uuidutils
+from neutron.tests.common import l3_test_common
from neutron.tests.common import machine_fixtures
from neutron.tests.common import net_helpers
from neutron.tests.functional.agent.linux import helpers
from neutron.tests.functional import base
-from neutron.tests.unit.agent.l3 import test_agent as test_l3_agent
+
LOG = logging.getLogger(__name__)
_uuid = uuidutils.generate_uuid
enable_fip = False
extra_routes = False
- return test_l3_agent.prepare_router_data(ip_version=ip_version,
+ return l3_test_common.prepare_router_data(ip_version=ip_version,
enable_snat=enable_snat,
enable_floating_ip=enable_fip,
enable_ha=enable_ha,
ip_version=4,
ipv6_subnet_modes=None,
interface_id=None):
- return test_l3_agent.router_append_subnet(router, count,
+ return l3_test_common.router_append_subnet(router, count,
ip_version, ipv6_subnet_modes, interface_id)
def _namespace_exists(self, namespace):
router_info_2 = copy.deepcopy(router_info)
router_info_2[l3_constants.HA_INTERFACE_KEY] = (
- test_l3_agent.get_ha_interface(ip='169.254.192.2',
- mac='22:22:22:22:22:22'))
+ l3_test_common.get_ha_interface(ip='169.254.192.2',
+ mac='22:22:22:22:22:22'))
get_ns_name.return_value = "%s%s%s" % (
namespaces.RouterNamespace._get_ns_name(router_info_2['id']),
def generate_dvr_router_info(
self, enable_ha=False, enable_snat=False, **kwargs):
- router = test_l3_agent.prepare_router_data(
+ router = l3_test_common.prepare_router_data(
enable_snat=enable_snat,
enable_floating_ip=True,
enable_ha=enable_ha,
# existing ports on the the uplinked subnet, the ARP
# cache is properly populated.
self.agent.conf.agent_mode = 'dvr_snat'
- router_info = test_l3_agent.prepare_router_data()
+ router_info = l3_test_common.prepare_router_data()
router_info['distributed'] = True
expected_neighbor = '35.4.1.10'
port_data = {
import netaddr
from oslo_log import log
import oslo_messaging
-from six import moves
from testtools import matchers
from neutron.agent.common import config as agent_config
from neutron.agent.l3 import agent as l3_agent
from neutron.agent.l3 import config as l3_config
-from neutron.agent.l3 import dvr_router
+from neutron.agent.l3 import dvr_edge_router as dvr_router
+from neutron.agent.l3 import dvr_local_router
from neutron.agent.l3 import dvr_snat_ns
from neutron.agent.l3 import ha
from neutron.agent.l3 import legacy_router
from neutron.openstack.common import uuidutils
from neutron.plugins.common import constants as p_const
from neutron.tests import base
+from neutron.tests.common import l3_test_common
_uuid = uuidutils.generate_uuid
HOSTNAME = 'myhost'
FIP_PRI = 32768
-class FakeDev(object):
- def __init__(self, name):
- self.name = name
-
-
-def router_append_interface(router, count=1, ip_version=4, ra_mode=None,
- addr_mode=None, dual_stack=False):
- interfaces = router[l3_constants.INTERFACE_KEY]
- current = sum(
- [netaddr.IPNetwork(subnet['cidr']).version == ip_version
- for p in interfaces for subnet in p['subnets']])
-
- mac_address = netaddr.EUI('ca:fe:de:ad:be:ef')
- mac_address.dialect = netaddr.mac_unix
- for i in range(current, current + count):
- fixed_ips = []
- subnets = []
- for loop_version in (4, 6):
- if loop_version == 4 and (ip_version == 4 or dual_stack):
- ip_pool = '35.4.%i.4'
- cidr_pool = '35.4.%i.0/24'
- prefixlen = 24
- gw_pool = '35.4.%i.1'
- elif loop_version == 6 and (ip_version == 6 or dual_stack):
- ip_pool = 'fd01:%x:1::6'
- cidr_pool = 'fd01:%x:1::/64'
- prefixlen = 64
- gw_pool = 'fd01:%x:1::1'
- else:
- continue
- subnet_id = _uuid()
- fixed_ips.append({'ip_address': ip_pool % i,
- 'subnet_id': subnet_id,
- 'prefixlen': prefixlen})
- subnets.append({'id': subnet_id,
- 'cidr': cidr_pool % i,
- 'gateway_ip': gw_pool % i,
- 'ipv6_ra_mode': ra_mode,
- 'ipv6_address_mode': addr_mode})
- if not fixed_ips:
- raise ValueError("Invalid ip_version: %s" % ip_version)
-
- interfaces.append(
- {'id': _uuid(),
- 'network_id': _uuid(),
- 'admin_state_up': True,
- 'fixed_ips': fixed_ips,
- 'mac_address': str(mac_address),
- 'subnets': subnets})
- mac_address.value += 1
-
-
-def router_append_subnet(router, count=1, ip_version=4,
- ipv6_subnet_modes=None, interface_id=None):
- if ip_version == 6:
- subnet_mode_none = {'ra_mode': None, 'address_mode': None}
- if not ipv6_subnet_modes:
- ipv6_subnet_modes = [subnet_mode_none] * count
- elif len(ipv6_subnet_modes) != count:
- ipv6_subnet_modes.extend([subnet_mode_none for i in
- moves.range(len(ipv6_subnet_modes),
- count)])
-
- if ip_version == 4:
- ip_pool = '35.4.%i.4'
- cidr_pool = '35.4.%i.0/24'
- prefixlen = 24
- gw_pool = '35.4.%i.1'
- elif ip_version == 6:
- ip_pool = 'fd01:%x::6'
- cidr_pool = 'fd01:%x::/64'
- prefixlen = 64
- gw_pool = 'fd01:%x::1'
- else:
- raise ValueError("Invalid ip_version: %s" % ip_version)
-
- interfaces = copy.deepcopy(router.get(l3_constants.INTERFACE_KEY, []))
- if interface_id:
- try:
- interface = next(i for i in interfaces
- if i['id'] == interface_id)
- except StopIteration:
- raise ValueError("interface_id not found")
-
- fixed_ips, subnets = interface['fixed_ips'], interface['subnets']
- else:
- interface = None
- fixed_ips, subnets = [], []
-
- num_existing_subnets = len(subnets)
- for i in moves.range(count):
- subnet_id = _uuid()
- fixed_ips.append(
- {'ip_address': ip_pool % (i + num_existing_subnets),
- 'subnet_id': subnet_id,
- 'prefixlen': prefixlen})
- subnets.append(
- {'id': subnet_id,
- 'cidr': cidr_pool % (i + num_existing_subnets),
- 'gateway_ip': gw_pool % (i + num_existing_subnets),
- 'ipv6_ra_mode': ipv6_subnet_modes[i]['ra_mode'],
- 'ipv6_address_mode': ipv6_subnet_modes[i]['address_mode']})
-
- if interface:
- # Update old interface
- index = interfaces.index(interface)
- interfaces[index].update({'fixed_ips': fixed_ips, 'subnets': subnets})
- else:
- # New interface appended to interfaces list
- mac_address = netaddr.EUI('ca:fe:de:ad:be:ef')
- mac_address.dialect = netaddr.mac_unix
- interfaces.append(
- {'id': _uuid(),
- 'network_id': _uuid(),
- 'admin_state_up': True,
- 'mac_address': str(mac_address),
- 'fixed_ips': fixed_ips,
- 'subnets': subnets})
-
- router[l3_constants.INTERFACE_KEY] = interfaces
-
-
-def prepare_router_data(ip_version=4, enable_snat=None, num_internal_ports=1,
- enable_floating_ip=False, enable_ha=False,
- extra_routes=False, dual_stack=False,
- v6_ext_gw_with_sub=True, **kwargs):
- fixed_ips = []
- subnets = []
- gateway_mac = kwargs.get('gateway_mac', 'ca:fe:de:ad:be:ee')
- for loop_version in (4, 6):
- if loop_version == 4 and (ip_version == 4 or dual_stack):
- ip_address = kwargs.get('ip_address', '19.4.4.4')
- prefixlen = 24
- subnet_cidr = kwargs.get('subnet_cidr', '19.4.4.0/24')
- gateway_ip = kwargs.get('gateway_ip', '19.4.4.1')
- elif (loop_version == 6 and (ip_version == 6 or dual_stack) and
- v6_ext_gw_with_sub):
- ip_address = kwargs.get('ip_address', 'fd00::4')
- prefixlen = 64
- subnet_cidr = kwargs.get('subnet_cidr', 'fd00::/64')
- gateway_ip = kwargs.get('gateway_ip', 'fd00::1')
- else:
- continue
- subnet_id = _uuid()
- fixed_ips.append({'ip_address': ip_address,
- 'subnet_id': subnet_id,
- 'prefixlen': prefixlen})
- subnets.append({'id': subnet_id,
- 'cidr': subnet_cidr,
- 'gateway_ip': gateway_ip})
- if not fixed_ips and v6_ext_gw_with_sub:
- raise ValueError("Invalid ip_version: %s" % ip_version)
-
- router_id = _uuid()
- ex_gw_port = {'id': _uuid(),
- 'mac_address': gateway_mac,
- 'network_id': _uuid(),
- 'fixed_ips': fixed_ips,
- 'subnets': subnets}
-
- routes = []
- if extra_routes:
- routes = [{'destination': '8.8.8.0/24', 'nexthop': '19.4.4.4'}]
-
- router = {
- 'id': router_id,
- 'distributed': False,
- l3_constants.INTERFACE_KEY: [],
- 'routes': routes,
- 'gw_port': ex_gw_port}
-
- if enable_floating_ip:
- router[l3_constants.FLOATINGIP_KEY] = [{
- 'id': _uuid(),
- 'port_id': _uuid(),
- 'status': 'DOWN',
- 'floating_ip_address': '19.4.4.2',
- 'fixed_ip_address': '10.0.0.1'}]
-
- router_append_interface(router, count=num_internal_ports,
- ip_version=ip_version, dual_stack=dual_stack)
- if enable_ha:
- router['ha'] = True
- router['ha_vr_id'] = 1
- router[l3_constants.HA_INTERFACE_KEY] = get_ha_interface()
-
- if enable_snat is not None:
- router['enable_snat'] = enable_snat
- return router
-
-
-def _get_subnet_id(port):
- return port['fixed_ips'][0]['subnet_id']
-
-
-#TODO(jschwarz): This is a shared function with both the unit tests
-# and the functional tests, and should be moved elsewhere (probably
-# neutron/tests/common/).
-def get_ha_interface(ip='169.254.192.1', mac='12:34:56:78:2b:5d'):
- subnet_id = _uuid()
- return {'admin_state_up': True,
- 'device_id': _uuid(),
- 'device_owner': 'network:router_ha_interface',
- 'fixed_ips': [{'ip_address': ip,
- 'prefixlen': 18,
- 'subnet_id': subnet_id}],
- 'id': _uuid(),
- 'mac_address': mac,
- 'name': u'L3 HA Admin port 0',
- 'network_id': _uuid(),
- 'status': u'ACTIVE',
- 'subnets': [{'cidr': '169.254.192.0/18',
- 'gateway_ip': '169.254.255.254',
- 'id': subnet_id}],
- 'tenant_id': '',
- 'agent_id': _uuid(),
- 'agent_host': 'aaa',
- 'priority': 1}
-
-
class BasicRouterOperationsFramework(base.BaseTestCase):
-
def setUp(self):
super(BasicRouterOperationsFramework, self).setUp()
mock.patch('eventlet.spawn').start()
l3_agent.L3NATAgent(HOSTNAME, self.conf)
def _test_internal_network_action(self, action):
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
router_id = router['id']
ri = l3router.RouterInfo(router_id, router, **self.ri_kwargs)
port = {'network_id': _uuid(),
return '%s/%s' % (fixed_ip['ip_address'], fixed_ip['prefixlen'])
def _test_internal_network_action_dist(self, action):
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
router_id = router['id']
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- ri = dvr_router.DvrRouter(
+ ri = dvr_router.DvrEdgeRouter(
agent, HOSTNAME, router_id, router, **self.ri_kwargs)
subnet_id = _uuid()
port = {'network_id': _uuid(),
if router.get('distributed'):
agent.conf.agent_mode = 'dvr_snat'
agent.host = HOSTNAME
- ri = dvr_router.DvrRouter(agent,
- HOSTNAME,
- router['id'],
- router,
- **self.ri_kwargs)
+ ri = dvr_router.DvrEdgeRouter(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()
else:
raise Exception("Invalid action %s" % action)
- def _prepare_ext_gw_test(self, ri, dual_stack=False):
- subnet_id = _uuid()
- fixed_ips = [{'subnet_id': subnet_id,
- 'ip_address': '20.0.0.30',
- 'prefixlen': 24}]
- subnets = [{'id': subnet_id,
- 'cidr': '20.0.0.0/24',
- 'gateway_ip': '20.0.0.1'}]
- if dual_stack:
- subnet_id_v6 = _uuid()
- fixed_ips.append({'subnet_id': subnet_id_v6,
- 'ip_address': '2001:192:168:100::2',
- 'prefixlen': 64})
- subnets.append({'id': subnet_id_v6,
- 'cidr': '2001:192:168:100::/64',
- 'gateway_ip': '2001:192:168:100::1'})
- ex_gw_port = {'fixed_ips': fixed_ips,
- 'subnets': subnets,
- 'extra_subnets': [{'cidr': '172.16.0.0/24'}],
- 'id': _uuid(),
- 'network_id': _uuid(),
- 'mac_address': 'ca:fe:de:ad:be:ef'}
- interface_name = ri.get_external_device_name(ex_gw_port['id'])
-
- self.device_exists.return_value = True
-
- return interface_name, ex_gw_port
-
def _test_external_gateway_updated(self, dual_stack=False):
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
ri.use_ipv6 = False
- interface_name, ex_gw_port = self._prepare_ext_gw_test(
- ri, dual_stack=dual_stack)
+ interface_name, ex_gw_port = l3_test_common.prepare_ext_gw_test(
+ self, ri, dual_stack=dual_stack)
fake_fip = {'floatingips': [{'id': _uuid(),
'floating_ip_address': '192.168.1.34',
def _test_ext_gw_updated_dvr_agent_mode(self, host,
agent_mode, expected_call_count):
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- ri = dvr_router.DvrRouter(agent,
- HOSTNAME,
- router['id'],
- router,
- **self.ri_kwargs)
+ ri = dvr_router.DvrEdgeRouter(agent,
+ HOSTNAME,
+ router['id'],
+ router,
+ **self.ri_kwargs)
ri.create_snat_namespace()
- interface_name, ex_gw_port = self._prepare_ext_gw_test(ri)
+ interface_name, ex_gw_port = l3_test_common.prepare_ext_gw_test(self,
+ ri)
ri._external_gateway_added = mock.Mock()
# test agent mode = dvr (compute node)
'dvr_snat', 1)
def test_agent_add_external_gateway(self):
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
self._test_external_gateway_action('add', router)
def test_agent_add_external_gateway_dual_stack(self):
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
self._test_external_gateway_action('add', router, dual_stack=True)
def test_agent_add_external_gateway_dist(self):
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
router['distributed'] = True
router['gw_port_host'] = HOSTNAME
self._test_external_gateway_action('add', router)
def test_agent_add_external_gateway_dist_dual_stack(self):
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
router['distributed'] = True
router['gw_port_host'] = HOSTNAME
self._test_external_gateway_action('add', router, dual_stack=True)
def test_agent_add_external_gateway_no_subnet(self):
- router = prepare_router_data(num_internal_ports=2,
- v6_ext_gw_with_sub=False)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2,
+ v6_ext_gw_with_sub=False)
self._test_external_gateway_action('add_no_sub', router)
def test_agent_add_external_gateway_no_subnet_with_ipv6_gw(self):
- router = prepare_router_data(num_internal_ports=2,
- v6_ext_gw_with_sub=False)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2,
+ v6_ext_gw_with_sub=False)
self._test_external_gateway_action('add_no_sub_v6_gw', router)
def test_agent_add_external_gateway_dual_stack_no_subnet_w_ipv6_gw(self):
- router = prepare_router_data(num_internal_ports=2,
- v6_ext_gw_with_sub=False)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2,
+ v6_ext_gw_with_sub=False)
self._test_external_gateway_action('add_no_sub_v6_gw',
router, dual_stack=True)
def test_agent_remove_external_gateway(self):
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
self._test_external_gateway_action('remove', router)
def test_agent_remove_external_gateway_dual_stack(self):
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
self._test_external_gateway_action('remove', router, dual_stack=True)
def test_agent_remove_external_gateway_dist(self):
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
router['distributed'] = True
router['gw_port_host'] = HOSTNAME
self._test_external_gateway_action('remove', router)
def test_agent_remove_external_gateway_dist_dual_stack(self):
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
router['distributed'] = True
router['gw_port_host'] = HOSTNAME
self._test_external_gateway_action('remove', router, dual_stack=True)
self.assertIn(r.rule, expected_rules)
def test__map_internal_interfaces(self):
- router = prepare_router_data(num_internal_ports=4)
- ri = dvr_router.DvrRouter(mock.sentinel.agent,
- HOSTNAME,
- router['id'],
- router,
- **self.ri_kwargs)
+ router = l3_test_common.prepare_router_data(num_internal_ports=4)
+ ri = dvr_router.DvrEdgeRouter(mock.sentinel.agent,
+ HOSTNAME,
+ router['id'],
+ router,
+ **self.ri_kwargs)
test_port = {
'mac_address': '00:12:23:34:45:56',
- 'fixed_ips': [{'subnet_id': _get_subnet_id(
+ 'fixed_ips': [{'subnet_id': l3_test_common.get_subnet_id(
router[l3_constants.INTERFACE_KEY][0]),
'ip_address': '101.12.13.14'}]}
internal_ports = ri.router.get(l3_constants.INTERFACE_KEY, [])
self.assertNotEqual(test_port, res_ip)
self.assertIsNone(res_ip)
- def test__set_subnet_arp_info(self):
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data(num_internal_ports=2)
- router['distributed'] = True
- ri = dvr_router.DvrRouter(
- agent, HOSTNAME, router['id'], router, **self.ri_kwargs)
- ports = ri.router.get(l3_constants.INTERFACE_KEY, [])
- subnet_id = _get_subnet_id(ports[0])
- test_ports = [{'mac_address': '00:11:22:33:44:55',
- 'device_owner': 'network:dhcp',
- 'fixed_ips': [{'ip_address': '1.2.3.4',
- 'prefixlen': 24,
- 'subnet_id': subnet_id}]}]
-
- self.plugin_api.get_ports_by_subnet.return_value = test_ports
-
- # Test basic case
- ports[0]['subnets'] = [{'id': subnet_id,
- 'cidr': '1.2.3.0/24'}]
- ri._set_subnet_arp_info(subnet_id)
- self.mock_ip_dev.neigh.add.assert_called_once_with(
- '1.2.3.4', '00:11:22:33:44:55')
-
- # Test negative case
- router['distributed'] = False
- ri._set_subnet_arp_info(subnet_id)
- self.mock_ip_dev.neigh.add.never_called()
-
- def test_add_arp_entry(self):
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data(num_internal_ports=2)
- router['distributed'] = True
- subnet_id = _get_subnet_id(router[l3_constants.INTERFACE_KEY][0])
- arp_table = {'ip_address': '1.7.23.11',
- 'mac_address': '00:11:22:33:44:55',
- 'subnet_id': subnet_id}
-
- payload = {'arp_table': arp_table, 'router_id': router['id']}
- agent._router_added(router['id'], router)
- agent.add_arp_entry(None, payload)
- agent.router_deleted(None, router['id'])
- self.mock_ip_dev.neigh.add.assert_called_once_with(
- '1.7.23.11', '00:11:22:33:44:55')
-
- def test_add_arp_entry_no_routerinfo(self):
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data(num_internal_ports=2)
- subnet_id = _get_subnet_id(router[l3_constants.INTERFACE_KEY][0])
- arp_table = {'ip_address': '1.7.23.11',
- 'mac_address': '00:11:22:33:44:55',
- 'subnet_id': subnet_id}
-
- payload = {'arp_table': arp_table, 'router_id': router['id']}
- agent.add_arp_entry(None, payload)
-
- def test__update_arp_entry_with_no_subnet(self):
- ri = dvr_router.DvrRouter(
- mock.sentinel.agent,
- HOSTNAME,
- 'foo_router_id',
- {'distributed': True, 'gw_port_host': HOSTNAME},
- **self.ri_kwargs)
- with mock.patch.object(l3_agent.ip_lib, 'IPDevice') as f:
- ri._update_arp_entry(mock.ANY, mock.ANY, 'foo_subnet_id', 'add')
- self.assertFalse(f.call_count)
-
- def test_del_arp_entry(self):
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data(num_internal_ports=2)
- router['distributed'] = True
- subnet_id = _get_subnet_id(router[l3_constants.INTERFACE_KEY][0])
- arp_table = {'ip_address': '1.5.25.15',
- 'mac_address': '00:44:33:22:11:55',
- 'subnet_id': subnet_id}
-
- payload = {'arp_table': arp_table, 'router_id': router['id']}
- agent._router_added(router['id'], router)
- # first add the entry
- agent.add_arp_entry(None, payload)
- # now delete it
- agent.del_arp_entry(None, payload)
- self.mock_ip_dev.neigh.delete.assert_called_once_with(
- '1.5.25.15', '00:44:33:22:11:55')
- agent.router_deleted(None, router['id'])
-
def test_process_cent_router(self):
- router = prepare_router_data()
+ router = l3_test_common.prepare_router_data()
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
self._test_process_router(ri, agent)
def test_process_dist_router(self):
- router = prepare_router_data()
+ router = l3_test_common.prepare_router_data()
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- ri = dvr_router.DvrRouter(agent,
- HOSTNAME,
- router['id'],
- router,
- **self.ri_kwargs)
- subnet_id = _get_subnet_id(router[l3_constants.INTERFACE_KEY][0])
+ ri = dvr_router.DvrEdgeRouter(agent,
+ HOSTNAME,
+ router['id'],
+ router,
+ **self.ri_kwargs)
+ subnet_id = l3_test_common.get_subnet_id(
+ router[l3_constants.INTERFACE_KEY][0])
ri.router['distributed'] = True
ri.router['_snat_router_interfaces'] = [{
'fixed_ips': [{'subnet_id': subnet_id,
ri.add_floating_ip.assert_called_once_with(
floating_ips[0], mock.sentinel.interface_name, device)
- def test_get_floating_agent_gw_interfaces(self):
- fake_network_id = _uuid()
- subnet_id = _uuid()
- agent_gateway_port = (
- [{'fixed_ips': [{'ip_address': '20.0.0.30',
- 'prefixlen': 24,
- 'subnet_id': subnet_id}],
- 'subnets': [{'id': subnet_id,
- 'cidr': '20.0.0.0/24',
- 'gateway_ip': '20.0.0.1'}],
- 'id': _uuid(),
- 'binding:host_id': 'myhost',
- 'device_owner': 'network:floatingip_agent_gateway',
- 'network_id': fake_network_id,
- 'mac_address': 'ca:fe:de:ad:be:ef'}]
- )
-
- router = prepare_router_data(enable_snat=True)
- router[l3_constants.FLOATINGIP_AGENT_INTF_KEY] = agent_gateway_port
- router['distributed'] = True
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- ri = dvr_router.DvrRouter(
- agent, HOSTNAME, router['id'], router, **self.ri_kwargs)
- self.assertEqual(
- agent_gateway_port[0],
- ri.get_floating_agent_gw_interface(fake_network_id))
-
@mock.patch.object(lla.LinkLocalAllocator, '_write')
def test_create_dvr_fip_interfaces(self, lla_write):
fake_network_id = _uuid()
'mac_address': 'ca:fe:de:ad:be:ef'}]
)
- router = prepare_router_data(enable_snat=True)
+ router = l3_test_common.prepare_router_data(enable_snat=True)
router[l3_constants.FLOATINGIP_KEY] = fake_floatingips['floatingips']
router[l3_constants.FLOATINGIP_AGENT_INTF_KEY] = agent_gateway_port
router['distributed'] = True
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- ri = dvr_router.DvrRouter(
+ ri = dvr_router.DvrEdgeRouter(
agent, HOSTNAME, router['id'], router, **self.ri_kwargs)
ext_gw_port = ri.router.get('gw_port')
ri.fip_ns.subscribe = mock.Mock()
ri.fip_ns.agent_router_gateway = mock.Mock()
- with mock.patch.object(ri, 'get_floating_ips') as fips,\
+ 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
'mac_address': 'ca:fe:de:ad:be:ef'}]
)
- router = prepare_router_data(enable_snat=True)
+ router = l3_test_common.prepare_router_data(enable_snat=True)
router[l3_constants.FLOATINGIP_KEY] = fake_floatingips['floatingips']
router[l3_constants.FLOATINGIP_AGENT_INTF_KEY] = agent_gateway_port
router['distributed'] = True
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- ri = dvr_router.DvrRouter(
+ ri = dvr_router.DvrEdgeRouter(
agent, HOSTNAME, router['id'], router, **self.ri_kwargs)
ext_gw_port = ri.router.get('gw_port')
ri.fip_ns = agent.get_fip_ns(ext_gw_port['network_id'])
'port_id': _uuid(),
'host': HOSTNAME}]}
- router = prepare_router_data(enable_snat=True)
+ router = l3_test_common.prepare_router_data(enable_snat=True)
router[l3_constants.FLOATINGIP_KEY] = fake_floatingips['floatingips']
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
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):
- fake_floatingips = {'floatingips': [
- {'id': _uuid(),
- 'host': HOSTNAME,
- 'floating_ip_address': '15.1.2.3',
- 'fixed_ip_address': '192.168.0.1',
- 'floating_network_id': mock.sentinel.ext_net_id,
- 'port_id': _uuid()},
- {'id': _uuid(),
- 'host': 'some-other-host',
- 'floating_ip_address': '15.1.2.4',
- 'fixed_ip_address': '192.168.0.10',
- 'floating_network_id': mock.sentinel.ext_net_id,
- 'port_id': _uuid()}]}
-
- router = prepare_router_data(enable_snat=True)
- router[l3_constants.FLOATINGIP_KEY] = fake_floatingips['floatingips']
- router['distributed'] = True
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- ri = dvr_router.DvrRouter(agent,
- HOSTNAME,
- router['id'],
- router,
- **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 = (
- {'fixed_ips': [{'ip_address': '20.0.0.30',
- 'subnet_id': subnet_id}],
- 'subnets': [{'id': subnet_id,
- 'cidr': '20.0.0.0/24',
- 'gateway_ip': '20.0.0.1'}],
- 'id': _uuid(),
- 'network_id': _uuid(),
- 'mac_address': 'ca:fe:de:ad:be:ef'}
- )
-
def test_process_router_snat_disabled(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data(enable_snat=True)
+ router = l3_test_common.prepare_router_data(enable_snat=True)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
ri.external_gateway_added = mock.Mock()
# Process with NAT
def test_process_router_snat_enabled(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data(enable_snat=False)
+ router = l3_test_common.prepare_router_data(enable_snat=False)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
ri.external_gateway_added = mock.Mock()
# Process without NAT
def test_process_router_interface_added(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data()
+ router = l3_test_common.prepare_router_data()
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
ri.external_gateway_added = mock.Mock()
# Process with NAT
ri.process(agent)
# Add an interface and reprocess
- router_append_interface(router)
+ l3_test_common.router_append_interface(router)
# Reassign the router object to RouterInfo
ri.router = router
ri.process(agent)
def _test_process_ipv6_only_or_dual_stack_gw(self, dual_stack=False):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data(ip_version=6, dual_stack=dual_stack)
+ router = l3_test_common.prepare_router_data(ip_version=6,
+ dual_stack=dual_stack)
# Get NAT rules without the gw_port
gw_port = router['gw_port']
router['gw_port'] = None
ri.process(agent)
orig_nat_rules = ri.iptables_manager.ipv4['nat'].rules[:]
# Add an IPv6 interface and reprocess
- router_append_interface(router, count=1, ip_version=6, ra_mode=ra_mode,
- addr_mode=addr_mode)
+ l3_test_common.router_append_interface(router, count=1,
+ ip_version=6, ra_mode=ra_mode,
+ addr_mode=addr_mode)
# Reassign the router object to RouterInfo
self._process_router_instance_for_agent(agent, ri, router)
# IPv4 NAT rules should not be changed by adding an IPv6 interface
self._process_router_instance_for_agent(agent, ri, router)
# Add an IPv6 interface with len(ipv6_subnet_modes) subnets
# and reprocess
- router_append_subnet(router, count=len(ipv6_subnet_modes),
- ip_version=6, ipv6_subnet_modes=ipv6_subnet_modes)
+ l3_test_common.router_append_subnet(
+ router,
+ count=len(ipv6_subnet_modes),
+ ip_version=6,
+ ipv6_subnet_modes=ipv6_subnet_modes)
# Reassign the router object to RouterInfo
self._process_router_instance_for_agent(agent, ri, router)
return ri
self.assertEqual(expected_calls, self.external_process.mock_calls)
def test_process_router_ipv6_interface_added(self):
- router = prepare_router_data()
+ router = l3_test_common.prepare_router_data()
ri = self._process_router_ipv6_interface_added(router)
self._assert_ri_process_enabled(ri, 'radvd')
# Expect radvd configured without prefix
self.utils_replace_file.call_args[0][1].split())
def test_process_router_ipv6_slaac_interface_added(self):
- router = prepare_router_data()
+ router = l3_test_common.prepare_router_data()
ri = self._process_router_ipv6_interface_added(
router, ra_mode=l3_constants.IPV6_SLAAC)
self._assert_ri_process_enabled(ri, 'radvd')
self.utils_replace_file.call_args[0][1].split())
def test_process_router_ipv6_subnets_added(self):
- router = prepare_router_data()
+ router = l3_test_common.prepare_router_data()
ri = self._process_router_ipv6_subnet_added(router, ipv6_subnet_modes=[
{'ra_mode': l3_constants.IPV6_SLAAC,
'address_mode': l3_constants.IPV6_SLAAC},
def test_process_router_ipv6_subnets_added_to_existing_port(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data()
+ router = l3_test_common.prepare_router_data()
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
agent.external_gateway_added = mock.Mock()
self._process_router_instance_for_agent(agent, ri, router)
# Add the first subnet on a new interface
- router_append_subnet(router, count=1, ip_version=6, ipv6_subnet_modes=[
- {'ra_mode': l3_constants.IPV6_SLAAC,
- 'address_mode': l3_constants.IPV6_SLAAC}])
+ l3_test_common.router_append_subnet(
+ router, count=1,
+ ip_version=6, ipv6_subnet_modes=[
+ {'ra_mode': l3_constants.IPV6_SLAAC,
+ 'address_mode': l3_constants.IPV6_SLAAC}])
self._process_router_instance_for_agent(agent, ri, router)
self._assert_ri_process_enabled(ri, 'radvd')
radvd_config = self.utils_replace_file.call_args[0][1].split()
self.utils_replace_file.reset_mock()
# Add the second subnet on the same interface
interface_id = router[l3_constants.INTERFACE_KEY][1]['id']
- router_append_subnet(router, count=1, ip_version=6, ipv6_subnet_modes=[
- {'ra_mode': l3_constants.IPV6_SLAAC,
- 'address_mode': l3_constants.IPV6_SLAAC}],
+ l3_test_common.router_append_subnet(
+ router, count=1,
+ ip_version=6,
+ ipv6_subnet_modes=[
+ {'ra_mode': l3_constants.IPV6_SLAAC,
+ 'address_mode': l3_constants.IPV6_SLAAC}],
interface_id=interface_id)
self._process_router_instance_for_agent(agent, ri, router)
# radvd should have been enabled again and the interface
def test_process_router_ipv6v4_interface_added(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data()
+ router = l3_test_common.prepare_router_data()
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
ri.external_gateway_added = mock.Mock()
# Process with NAT
ri.process(agent)
# Add an IPv4 and IPv6 interface and reprocess
- router_append_interface(router, count=1, ip_version=4)
- router_append_interface(router, count=1, ip_version=6)
+ l3_test_common.router_append_interface(router, count=1, ip_version=4)
+ l3_test_common.router_append_interface(router, count=1, ip_version=6)
# Reassign the router object to RouterInfo
self._process_router_instance_for_agent(agent, ri, router)
self._assert_ri_process_enabled(ri, 'radvd')
def test_process_router_interface_removed(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
ri.external_gateway_added = mock.Mock()
# Process with NAT
def test_process_router_ipv6_interface_removed(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data()
+ router = l3_test_common.prepare_router_data()
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
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)
+ l3_test_common.router_append_interface(router, count=1, ip_version=6)
self._process_router_instance_for_agent(agent, ri, router)
self._assert_ri_process_enabled(ri, 'radvd')
# Reset the calls so we can check for disable radvd
def test_process_router_ipv6_subnet_removed(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data()
+ router = l3_test_common.prepare_router_data()
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
agent.external_gateway_added = mock.Mock()
self._process_router_instance_for_agent(agent, ri, router)
# Add an IPv6 interface with two subnets and reprocess
- router_append_subnet(router, count=2, ip_version=6,
- ipv6_subnet_modes=([
- {'ra_mode': l3_constants.IPV6_SLAAC,
- 'address_mode': l3_constants.IPV6_SLAAC}
- ] * 2))
+ l3_test_common.router_append_subnet(
+ router, count=2, ip_version=6,
+ ipv6_subnet_modes=([{'ra_mode': l3_constants.IPV6_SLAAC,
+ 'address_mode': l3_constants.IPV6_SLAAC}]
+ * 2))
self._process_router_instance_for_agent(agent, ri, router)
self._assert_ri_process_enabled(ri, 'radvd')
# Reset mocks to check for modified radvd config
def test_process_router_internal_network_added_unexpected_error(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data()
+ router = l3_test_common.prepare_router_data()
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
ri.external_gateway_added = mock.Mock()
with mock.patch.object(
def test_process_router_internal_network_removed_unexpected_error(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data()
+ router = l3_test_common.prepare_router_data()
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
ri.external_gateway_added = mock.Mock()
# add an internal port
with mock.patch.object(
agent.plugin_rpc, 'update_floatingip_statuses'
) as mock_update_fip_status:
- router = prepare_router_data(num_internal_ports=1)
+ router = l3_test_common.prepare_router_data(num_internal_ports=1)
fip1 = {'id': _uuid(), 'floating_ip_address': '8.8.8.8',
'fixed_ip_address': '7.7.7.7', 'status': 'ACTIVE',
'port_id': router[l3_constants.INTERFACE_KEY][0]['id']}
agent.plugin_rpc,
'update_floatingip_statuses') as mock_update_fip_status:
fip_id = _uuid()
- router = prepare_router_data(num_internal_ports=1)
+ router = l3_test_common.prepare_router_data(num_internal_ports=1)
router[l3_constants.FLOATINGIP_KEY] = [
{'id': fip_id,
'floating_ip_address': '8.8.8.8',
agent.plugin_rpc,
'update_floatingip_statuses') as mock_update_fip_status:
fip_id = _uuid()
- router = prepare_router_data(num_internal_ports=1)
+ router = l3_test_common.prepare_router_data(num_internal_ports=1)
router[l3_constants.FLOATINGIP_KEY] = [
{'id': fip_id,
'floating_ip_address': '8.8.8.8',
agent.plugin_rpc,
'update_floatingip_statuses') as mock_update_fip_status:
fip_id = _uuid()
- router = prepare_router_data(num_internal_ports=1)
+ router = l3_test_common.prepare_router_data(num_internal_ports=1)
router[l3_constants.FLOATINGIP_KEY] = [
{'id': fip_id,
'floating_ip_address': '8.8.8.8',
def test_handle_router_snat_rules_distributed_without_snat_manager(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- ri = dvr_router.DvrRouter(
+ ri = dvr_router.DvrEdgeRouter(
agent,
HOSTNAME,
'foo_router_id',
**self.ri_kwargs)
ri.iptables_manager = mock.Mock()
- with mock.patch.object(dvr_router.LOG, 'debug') as log_debug:
+ with mock.patch.object(dvr_local_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)
def test_process_router_delete_stale_internal_devices(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- stale_devlist = [FakeDev('qr-a1b2c3d4-e5'),
- FakeDev('qr-b2c3d4e5-f6')]
+ stale_devlist = [l3_test_common.FakeDev('qr-a1b2c3d4-e5'),
+ l3_test_common.FakeDev('qr-b2c3d4e5-f6')]
stale_devnames = [dev.name for dev in stale_devlist]
get_devices_return = []
get_devices_return.extend(stale_devlist)
self.mock_ip.get_devices.return_value = get_devices_return
- router = prepare_router_data(enable_snat=True, num_internal_ports=1)
+ router = l3_test_common.prepare_router_data(enable_snat=True,
+ num_internal_ports=1)
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
internal_ports = ri.router.get(l3_constants.INTERFACE_KEY, [])
def test_process_router_delete_stale_external_devices(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- stale_devlist = [FakeDev('qg-a1b2c3d4-e5')]
+ stale_devlist = [l3_test_common.FakeDev('qg-a1b2c3d4-e5')]
stale_devnames = [dev.name for dev in stale_devlist]
- router = prepare_router_data(enable_snat=True, num_internal_ports=1)
+ router = l3_test_common.prepare_router_data(enable_snat=True,
+ num_internal_ports=1)
del router['gw_port']
ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
namespace = 'qrouter-bar'
self.mock_ip.get_namespaces.return_value = [namespace]
- self.mock_ip.get_devices.return_value = [FakeDev('qr-aaaa'),
- FakeDev('rfp-aaaa')]
+ self.mock_ip.get_devices.return_value = [
+ l3_test_common.FakeDev('qr-aaaa'),
+ l3_test_common.FakeDev('rfp-aaaa')]
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
def test_create_dvr_gateway(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- router = prepare_router_data()
- ri = dvr_router.DvrRouter(agent,
- HOSTNAME,
- router['id'],
- router,
- **self.ri_kwargs)
+ router = l3_test_common.prepare_router_data()
+ ri = dvr_router.DvrEdgeRouter(agent,
+ HOSTNAME,
+ router['id'],
+ router,
+ **self.ri_kwargs)
port_id = _uuid()
subnet_id = _uuid()
self.assertRaises(oslo_messaging.MessagingTimeout, l3_agent.L3NATAgent,
HOSTNAME, self.conf)
- def _test_external_gateway_removed_ext_gw_port_and_fip(self, fip_ns=False):
+ def test_external_gateway_removed_ext_gw_port_no_fip_ns(self):
self.conf.set_override('state_path', '/tmp')
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
agent.conf.agent_mode = 'dvr_snat'
- router = prepare_router_data(num_internal_ports=2)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
router['gw_port_host'] = HOSTNAME
self.mock_driver.unplug.reset_mock()
external_net_id = router['gw_port']['network_id']
- ri = dvr_router.DvrRouter(
+ ri = dvr_router.DvrEdgeRouter(
agent, HOSTNAME, router['id'], router, **self.ri_kwargs)
ri.remove_floating_ip = mock.Mock()
agent._fetch_external_net_id = mock.Mock(return_value=external_net_id)
nat = ri.iptables_manager.ipv4['nat']
nat.clear_rules_by_tag = mock.Mock()
nat.add_rule = mock.Mock()
- if fip_ns:
- ri.fip_ns = agent.get_fip_ns(external_net_id)
- subnet_id = _uuid()
- ri.fip_ns.agent_gateway_port = {
- 'fixed_ips': [{
- 'ip_address': '20.0.0.30',
- 'prefixlen': 24,
- 'subnet_id': subnet_id
- }],
- 'subnets': [{'id': subnet_id,
- 'cidr': '20.0.0.0/24',
- 'gateway_ip': '20.0.0.1'}],
- 'id': _uuid(),
- 'network_id': external_net_id,
- 'mac_address': 'ca:fe:de:ad:be:ef'}
-
- 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 = [
- FakeDev(ri.fip_ns.get_ext_device_name(_uuid()))]
- self.mock_ip_dev.addr.list.return_value = [
- {'cidr': vm_floating_ip + '/32'},
- {'cidr': '19.4.4.1/24'}]
- self.device_exists.return_value = True
- fip_ns = ri.fip_ns
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,
- '19.4.4.2/32')
- else:
- self.assertFalse(ri.remove_floating_ip.called)
-
- def test_external_gateway_removed_ext_gw_port_and_fip(self):
- self._test_external_gateway_removed_ext_gw_port_and_fip(fip_ns=True)
-
- def test_external_gateway_removed_ext_gw_port_no_fip_ns(self):
- self._test_external_gateway_removed_ext_gw_port_and_fip(fip_ns=False)
+ self.assertFalse(ri.remove_floating_ip.called)
def test_spawn_radvd(self):
- router = prepare_router_data(ip_version=6)
+ router = l3_test_common.prepare_router_data(ip_version=6)
conffile = '/fake/radvd.conf'
pidfile = '/fake/radvd.pid'
router['id'],
namespaces.RouterNamespace._get_ns_name(router['id']),
agent.process_monitor,
- FakeDev)
+ l3_test_common.FakeDev)
radvd.enable(router['_interfaces'])
cmd = execute.call_args[0][0]
for mode_list in mode_combos:
ipv6_subnet_modes = [{'ra_mode': mode, 'address_mode': mode}
for mode in mode_list]
- router = prepare_router_data()
+ router = l3_test_common.prepare_router_data()
ri = self._process_router_ipv6_subnet_added(router,
ipv6_subnet_modes)
--- /dev/null
+# Copyright (c) 2015 Openstack Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import mock
+import netaddr
+
+from oslo_log import log
+
+from neutron.agent.common import config as agent_config
+from neutron.agent.l3 import agent as l3_agent
+from neutron.agent.l3 import config as l3_config
+from neutron.agent.l3 import dvr_local_router as dvr_router
+from neutron.agent.l3 import ha
+from neutron.agent.l3 import link_local_allocator as lla
+from neutron.agent.l3 import router_info
+from neutron.agent.linux import external_process
+from neutron.agent.linux import interface
+from neutron.agent.linux import ip_lib
+from neutron.callbacks import manager
+from neutron.callbacks import registry
+from neutron.common import config as base_config
+from neutron.common import constants as l3_constants
+from neutron.common import utils as common_utils
+from neutron.openstack.common import uuidutils
+from neutron.tests import base
+from neutron.tests.common import l3_test_common
+
+_uuid = uuidutils.generate_uuid
+FIP_PRI = 32768
+HOSTNAME = 'myhost'
+
+
+class TestDvrRouterOperations(base.BaseTestCase):
+
+ def setUp(self):
+ super(TestDvrRouterOperations, self).setUp()
+ mock.patch('eventlet.spawn').start()
+ self.conf = agent_config.setup_conf()
+ self.conf.register_opts(base_config.core_opts)
+ log.register_options(self.conf)
+ self.conf.register_opts(agent_config.AGENT_STATE_OPTS, 'AGENT')
+ self.conf.register_opts(l3_config.OPTS)
+ self.conf.register_opts(ha.OPTS)
+ agent_config.register_interface_driver_opts_helper(self.conf)
+ agent_config.register_use_namespaces_opts_helper(self.conf)
+ agent_config.register_process_monitor_opts(self.conf)
+ self.conf.register_opts(interface.OPTS)
+ self.conf.register_opts(external_process.OPTS)
+ self.conf.set_override('router_id', 'fake_id')
+ self.conf.set_override('interface_driver',
+ 'neutron.agent.linux.interface.NullDriver')
+ self.conf.set_override('send_arp_for_ha', 1)
+ self.conf.set_override('state_path', '')
+
+ self.device_exists_p = mock.patch(
+ 'neutron.agent.linux.ip_lib.device_exists')
+ self.device_exists = self.device_exists_p.start()
+
+ self.ensure_dir = mock.patch('neutron.agent.linux.utils'
+ '.ensure_dir').start()
+
+ mock.patch('neutron.agent.linux.keepalived.KeepalivedManager'
+ '.get_full_config_file_path').start()
+
+ self.utils_exec_p = mock.patch(
+ 'neutron.agent.linux.utils.execute')
+ self.utils_exec = self.utils_exec_p.start()
+
+ self.utils_replace_file_p = mock.patch(
+ 'neutron.agent.linux.utils.replace_file')
+ self.utils_replace_file = self.utils_replace_file_p.start()
+
+ self.external_process_p = mock.patch(
+ 'neutron.agent.linux.external_process.ProcessManager')
+ self.external_process = self.external_process_p.start()
+ self.process_monitor = mock.patch(
+ 'neutron.agent.linux.external_process.ProcessMonitor').start()
+
+ self.send_adv_notif_p = mock.patch(
+ 'neutron.agent.linux.ip_lib.send_ip_addr_adv_notif')
+ self.send_adv_notif = self.send_adv_notif_p.start()
+
+ self.dvr_cls_p = mock.patch('neutron.agent.linux.interface.NullDriver')
+ driver_cls = self.dvr_cls_p.start()
+ self.mock_driver = mock.MagicMock()
+ self.mock_driver.DEV_NAME_LEN = (
+ interface.LinuxInterfaceDriver.DEV_NAME_LEN)
+ driver_cls.return_value = self.mock_driver
+
+ self.ip_cls_p = mock.patch('neutron.agent.linux.ip_lib.IPWrapper')
+ ip_cls = self.ip_cls_p.start()
+ self.mock_ip = mock.MagicMock()
+ ip_cls.return_value = self.mock_ip
+
+ ip_rule = mock.patch('neutron.agent.linux.ip_lib.IPRule').start()
+ self.mock_rule = mock.MagicMock()
+ ip_rule.return_value = self.mock_rule
+
+ ip_dev = mock.patch('neutron.agent.linux.ip_lib.IPDevice').start()
+ self.mock_ip_dev = mock.MagicMock()
+ ip_dev.return_value = self.mock_ip_dev
+
+ self.l3pluginApi_cls_p = mock.patch(
+ 'neutron.agent.l3.agent.L3PluginApi')
+ l3pluginApi_cls = self.l3pluginApi_cls_p.start()
+ self.plugin_api = mock.MagicMock()
+ l3pluginApi_cls.return_value = self.plugin_api
+
+ self.looping_call_p = mock.patch(
+ 'neutron.openstack.common.loopingcall.FixedIntervalLoopingCall')
+ self.looping_call_p.start()
+
+ subnet_id_1 = _uuid()
+ subnet_id_2 = _uuid()
+ self.snat_ports = [{'subnets': [{'cidr': '152.2.0.0/16',
+ 'gateway_ip': '152.2.0.1',
+ 'id': subnet_id_1}],
+ 'network_id': _uuid(),
+ 'device_owner': 'network:router_centralized_snat',
+ 'mac_address': 'fa:16:3e:80:8d:80',
+ 'fixed_ips': [{'subnet_id': subnet_id_1,
+ 'ip_address': '152.2.0.13',
+ 'prefixlen': 16}],
+ 'id': _uuid(), 'device_id': _uuid()},
+ {'subnets': [{'cidr': '152.10.0.0/16',
+ 'gateway_ip': '152.10.0.1',
+ 'id': subnet_id_2}],
+ 'network_id': _uuid(),
+ 'device_owner': 'network:router_centralized_snat',
+ 'mac_address': 'fa:16:3e:80:8d:80',
+ 'fixed_ips': [{'subnet_id': subnet_id_2,
+ 'ip_address': '152.10.0.13',
+ 'prefixlen': 16}],
+ 'id': _uuid(), 'device_id': _uuid()}]
+
+ self.ri_kwargs = {'agent_conf': self.conf,
+ 'interface_driver': self.mock_driver}
+
+ self._callback_manager = manager.CallbacksManager()
+ mock.patch.object(registry, '_get_callback_manager',
+ return_value=self._callback_manager).start()
+
+ def _create_router(self, router=None, **kwargs):
+ agent_conf = mock.Mock()
+ self.router_id = _uuid()
+ if not router:
+ router = mock.MagicMock()
+ return dvr_router.DvrLocalRouter(mock.sentinel.agent,
+ mock.sentinel.myhost,
+ self.router_id,
+ router,
+ agent_conf,
+ mock.sentinel.interface_driver,
+ **kwargs)
+
+ def test_get_floating_ips_dvr(self):
+ router = mock.MagicMock()
+ router.get.return_value = [{'host': mock.sentinel.myhost},
+ {'host': mock.sentinel.otherhost}]
+ ri = self._create_router(router)
+
+ fips = ri.get_floating_ips()
+
+ self.assertEqual([{'host': mock.sentinel.myhost}], fips)
+
+ @mock.patch.object(ip_lib, 'send_ip_addr_adv_notif')
+ @mock.patch.object(ip_lib, 'IPDevice')
+ @mock.patch.object(ip_lib, 'IPRule')
+ def test_floating_ip_added_dist(self, mIPRule, mIPDevice, mock_adv_notif):
+ router = mock.MagicMock()
+ ri = self._create_router(router)
+ ext_net_id = _uuid()
+ subnet_id = _uuid()
+ agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30',
+ 'prefixlen': 24,
+ 'subnet_id': subnet_id}],
+ 'subnets': [{'id': subnet_id,
+ 'cidr': '20.0.0.0/24',
+ 'gateway_ip': '20.0.0.1'}],
+ 'id': _uuid(),
+ 'network_id': ext_net_id,
+ 'mac_address': 'ca:fe:de:ad:be:ef'}
+
+ fip = {'id': _uuid(),
+ 'host': HOSTNAME,
+ 'floating_ip_address': '15.1.2.3',
+ 'fixed_ip_address': '192.168.0.1',
+ 'floating_network_id': ext_net_id,
+ 'port_id': _uuid()}
+ ri.fip_ns = mock.Mock()
+ ri.fip_ns.agent_gateway_port = agent_gw_port
+ ri.fip_ns.allocate_rule_priority.return_value = FIP_PRI
+ ri.rtr_fip_subnet = lla.LinkLocalAddressPair('169.254.30.42/31')
+ 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('192.168.0.1', 16, FIP_PRI)
+ self.assertEqual(1, ri.dist_fip_count)
+ # TODO(mrsmith): add more asserts
+
+ @mock.patch.object(ip_lib, 'IPWrapper')
+ @mock.patch.object(ip_lib, 'IPDevice')
+ @mock.patch.object(ip_lib, 'IPRule')
+ def test_floating_ip_removed_dist(self, mIPRule, mIPDevice, mIPWrapper):
+ router = mock.MagicMock()
+ ri = self._create_router(router)
+
+ subnet_id = _uuid()
+ agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30',
+ 'prefixlen': 24,
+ 'subnet_id': subnet_id}],
+ 'subnets': [{'id': subnet_id,
+ 'cidr': '20.0.0.0/24',
+ 'gateway_ip': '20.0.0.1'}],
+ 'id': _uuid(),
+ '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
+ ri.fip_2_rtr = '11.22.33.42'
+ ri.rtr_2_fip = '11.22.33.40'
+ ri.fip_ns.agent_gateway_port = agent_gw_port
+ s = lla.LinkLocalAddressPair('169.254.30.42/31')
+ ri.rtr_fip_subnet = s
+ ri.floating_ip_removed_dist(fip_cidr)
+ mIPRule().rule.delete.assert_called_with(
+ str(netaddr.IPNetwork(fip_cidr).ip), 16, FIP_PRI)
+ mIPDevice().route.delete_route.assert_called_with(fip_cidr, str(s.ip))
+ self.assertFalse(ri.fip_ns.unsubscribe.called)
+
+ ri.dist_fip_count = 1
+ ri.rtr_fip_subnet = lla.LinkLocalAddressPair('15.1.2.3/32')
+ _, fip_to_rtr = ri.rtr_fip_subnet.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']))
+ mIPDevice().route.delete_gateway.assert_called_once_with(
+ str(fip_to_rtr.ip), table=16)
+ fip_ns.unsubscribe.assert_called_once_with(ri.router_id)
+
+ def _test_add_floating_ip(self, ri, fip, is_failure):
+ ri._add_fip_addr_to_device = mock.Mock(return_value=is_failure)
+ ri.floating_ip_added_dist = mock.Mock()
+
+ result = ri.add_floating_ip(fip,
+ mock.sentinel.interface_name,
+ mock.sentinel.device)
+ ri._add_fip_addr_to_device.assert_called_once_with(
+ fip, mock.sentinel.device)
+ return result
+
+ def test_add_floating_ip(self):
+ ri = self._create_router(mock.MagicMock())
+ ip = '15.1.2.3'
+ fip = {'floating_ip_address': ip}
+ result = self._test_add_floating_ip(ri, fip, True)
+ ri.floating_ip_added_dist.assert_called_once_with(fip, ip + '/32')
+ self.assertEqual(l3_constants.FLOATINGIP_STATUS_ACTIVE, result)
+
+ def test_add_floating_ip_error(self):
+ ri = self._create_router(mock.MagicMock())
+ result = self._test_add_floating_ip(
+ ri, {'floating_ip_address': '15.1.2.3'}, False)
+ self.assertFalse(ri.floating_ip_added_dist.called)
+ self.assertEqual(l3_constants.FLOATINGIP_STATUS_ERROR, result)
+
+ @mock.patch.object(router_info.RouterInfo, 'remove_floating_ip')
+ def test_remove_floating_ip(self, super_remove_floating_ip):
+ ri = self._create_router(mock.MagicMock())
+ ri.floating_ip_removed_dist = mock.Mock()
+
+ ri.remove_floating_ip(mock.sentinel.device, mock.sentinel.ip_cidr)
+
+ super_remove_floating_ip.assert_called_once_with(
+ mock.sentinel.device, mock.sentinel.ip_cidr)
+ ri.floating_ip_removed_dist.assert_called_once_with(
+ mock.sentinel.ip_cidr)
+
+ def test__get_internal_port(self):
+ ri = self._create_router()
+ port = {'fixed_ips': [{'subnet_id': mock.sentinel.subnet_id}]}
+ router_ports = [port]
+ ri.router.get.return_value = router_ports
+ self.assertEqual(port, ri._get_internal_port(mock.sentinel.subnet_id))
+
+ def test__get_internal_port_not_found(self):
+ ri = self._create_router()
+ port = {'fixed_ips': [{'subnet_id': mock.sentinel.subnet_id}]}
+ router_ports = [port]
+ ri.router.get.return_value = router_ports
+ self.assertEqual(None, ri._get_internal_port(mock.sentinel.subnet_id2))
+
+ def test__get_snat_idx_ipv4(self):
+ ip_cidr = '101.12.13.00/24'
+ ri = self._create_router(mock.MagicMock())
+ snat_idx = ri._get_snat_idx(ip_cidr)
+ # 0x650C0D00 is numerical value of 101.12.13.00
+ self.assertEqual(0x650C0D00, snat_idx)
+
+ def test__get_snat_idx_ipv6(self):
+ ip_cidr = '2620:0:a03:e100::/64'
+ ri = self._create_router(mock.MagicMock())
+ snat_idx = ri._get_snat_idx(ip_cidr)
+ # 0x3D345705 is 30 bit xor folded crc32 of the ip_cidr
+ self.assertEqual(0x3D345705, snat_idx)
+
+ def test__get_snat_idx_ipv6_below_32768(self):
+ ip_cidr = 'd488::/30'
+ # crc32 of this ip_cidr is 0x1BD7
+ ri = self._create_router(mock.MagicMock())
+ snat_idx = ri._get_snat_idx(ip_cidr)
+ # 0x1BD7 + 0x3FFFFFFF = 0x40001BD6
+ self.assertEqual(0x40001BD6, snat_idx)
+
+ def test__set_subnet_arp_info(self):
+ agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
+ router['distributed'] = True
+ ri = dvr_router.DvrLocalRouter(
+ agent, HOSTNAME, router['id'], router, **self.ri_kwargs)
+ ports = ri.router.get(l3_constants.INTERFACE_KEY, [])
+ subnet_id = l3_test_common.get_subnet_id(ports[0])
+ test_ports = [{'mac_address': '00:11:22:33:44:55',
+ 'device_owner': 'network:dhcp',
+ 'fixed_ips': [{'ip_address': '1.2.3.4',
+ 'prefixlen': 24,
+ 'subnet_id': subnet_id}]}]
+
+ self.plugin_api.get_ports_by_subnet.return_value = test_ports
+
+ # Test basic case
+ ports[0]['subnets'] = [{'id': subnet_id,
+ 'cidr': '1.2.3.0/24'}]
+ ri._set_subnet_arp_info(subnet_id)
+ self.mock_ip_dev.neigh.add.assert_called_once_with(
+ '1.2.3.4', '00:11:22:33:44:55')
+
+ # Test negative case
+ router['distributed'] = False
+ ri._set_subnet_arp_info(subnet_id)
+ self.mock_ip_dev.neigh.add.never_called()
+
+ def test_add_arp_entry(self):
+ agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
+ router['distributed'] = True
+ subnet_id = l3_test_common.get_subnet_id(
+ router[l3_constants.INTERFACE_KEY][0])
+ arp_table = {'ip_address': '1.7.23.11',
+ 'mac_address': '00:11:22:33:44:55',
+ 'subnet_id': subnet_id}
+
+ payload = {'arp_table': arp_table, 'router_id': router['id']}
+ agent._router_added(router['id'], router)
+ agent.add_arp_entry(None, payload)
+ agent.router_deleted(None, router['id'])
+ self.mock_ip_dev.neigh.add.assert_called_once_with(
+ '1.7.23.11', '00:11:22:33:44:55')
+
+ def test_add_arp_entry_no_routerinfo(self):
+ agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
+ subnet_id = l3_test_common.get_subnet_id(
+ router[l3_constants.INTERFACE_KEY][0])
+ arp_table = {'ip_address': '1.7.23.11',
+ 'mac_address': '00:11:22:33:44:55',
+ 'subnet_id': subnet_id}
+
+ payload = {'arp_table': arp_table, 'router_id': router['id']}
+ agent.add_arp_entry(None, payload)
+
+ def test__update_arp_entry_with_no_subnet(self):
+ ri = dvr_router.DvrLocalRouter(
+ mock.sentinel.agent,
+ HOSTNAME,
+ 'foo_router_id',
+ {'distributed': True, 'gw_port_host': HOSTNAME},
+ **self.ri_kwargs)
+ with mock.patch.object(l3_agent.ip_lib, 'IPDevice') as f:
+ ri._update_arp_entry(mock.ANY, mock.ANY, 'foo_subnet_id', 'add')
+ self.assertFalse(f.call_count)
+
+ def test_del_arp_entry(self):
+ agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
+ router['distributed'] = True
+ subnet_id = l3_test_common.get_subnet_id(
+ router[l3_constants.INTERFACE_KEY][0])
+ arp_table = {'ip_address': '1.5.25.15',
+ 'mac_address': '00:44:33:22:11:55',
+ 'subnet_id': subnet_id}
+
+ payload = {'arp_table': arp_table, 'router_id': router['id']}
+ agent._router_added(router['id'], router)
+ # first add the entry
+ agent.add_arp_entry(None, payload)
+ # now delete it
+ agent.del_arp_entry(None, payload)
+ self.mock_ip_dev.neigh.delete.assert_called_once_with(
+ '1.5.25.15', '00:44:33:22:11:55')
+ agent.router_deleted(None, router['id'])
+
+ def test_get_floating_agent_gw_interfaces(self):
+ fake_network_id = _uuid()
+ subnet_id = _uuid()
+ agent_gateway_port = (
+ [{'fixed_ips': [{'ip_address': '20.0.0.30',
+ 'prefixlen': 24,
+ 'subnet_id': subnet_id}],
+ 'subnets': [{'id': subnet_id,
+ 'cidr': '20.0.0.0/24',
+ 'gateway_ip': '20.0.0.1'}],
+ 'id': _uuid(),
+ 'binding:host_id': 'myhost',
+ 'device_owner': 'network:floatingip_agent_gateway',
+ 'network_id': fake_network_id,
+ 'mac_address': 'ca:fe:de:ad:be:ef'}]
+ )
+
+ router = l3_test_common.prepare_router_data(enable_snat=True)
+ router[l3_constants.FLOATINGIP_AGENT_INTF_KEY] = agent_gateway_port
+ router['distributed'] = True
+ agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+ ri = dvr_router.DvrLocalRouter(
+ agent, HOSTNAME, router['id'], router, **self.ri_kwargs)
+ self.assertEqual(
+ agent_gateway_port[0],
+ ri.get_floating_agent_gw_interface(fake_network_id))
+
+ def test_process_router_dist_floating_ip_add(self):
+ fake_floatingips = {'floatingips': [
+ {'id': _uuid(),
+ 'host': HOSTNAME,
+ 'floating_ip_address': '15.1.2.3',
+ 'fixed_ip_address': '192.168.0.1',
+ 'floating_network_id': mock.sentinel.ext_net_id,
+ 'port_id': _uuid()},
+ {'id': _uuid(),
+ 'host': 'some-other-host',
+ 'floating_ip_address': '15.1.2.4',
+ 'fixed_ip_address': '192.168.0.10',
+ 'floating_network_id': mock.sentinel.ext_net_id,
+ 'port_id': _uuid()}]}
+
+ router = l3_test_common.prepare_router_data(enable_snat=True)
+ router[l3_constants.FLOATINGIP_KEY] = fake_floatingips['floatingips']
+ router['distributed'] = True
+ agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+ ri = dvr_router.DvrLocalRouter(agent,
+ HOSTNAME,
+ router['id'],
+ router,
+ **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 = (
+ {'fixed_ips': [{'ip_address': '20.0.0.30',
+ 'subnet_id': subnet_id}],
+ 'subnets': [{'id': subnet_id,
+ 'cidr': '20.0.0.0/24',
+ 'gateway_ip': '20.0.0.1'}],
+ 'id': _uuid(),
+ 'network_id': _uuid(),
+ 'mac_address': 'ca:fe:de:ad:be:ef'}
+ )
+
+ def _test_ext_gw_updated_dvr_agent_mode(self, host,
+ agent_mode, expected_call_count):
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
+ agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+ ri = dvr_router.DvrLocalRouter(agent,
+ HOSTNAME,
+ router['id'],
+ router,
+ **self.ri_kwargs)
+
+ interface_name, ex_gw_port = l3_test_common.prepare_ext_gw_test(self,
+ ri)
+ ri._external_gateway_added = mock.Mock()
+
+ # test agent mode = dvr (compute node)
+ router['gw_port_host'] = host
+ agent.conf.agent_mode = agent_mode
+
+ ri.external_gateway_updated(ex_gw_port, interface_name)
+ # no gateway should be added on dvr node
+ self.assertEqual(expected_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
+ self._test_ext_gw_updated_dvr_agent_mode('any-foo', 'dvr', 0)
+
+ def test_ext_gw_updated_dvr_agent_mode_host(self):
+ # no gateway should be added on dvr node
+ self._test_ext_gw_updated_dvr_agent_mode(HOSTNAME,
+ 'dvr', 0)
+
+ def test_external_gateway_removed_ext_gw_port_and_fip(self):
+ self.conf.set_override('state_path', '/tmp')
+
+ agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+ agent.conf.agent_mode = 'dvr'
+ router = l3_test_common.prepare_router_data(num_internal_ports=2)
+ router['gw_port_host'] = HOSTNAME
+ self.mock_driver.unplug.reset_mock()
+
+ external_net_id = router['gw_port']['network_id']
+ ri = dvr_router.DvrLocalRouter(
+ agent, HOSTNAME, router['id'], router, **self.ri_kwargs)
+ ri.remove_floating_ip = mock.Mock()
+ agent._fetch_external_net_id = mock.Mock(return_value=external_net_id)
+ ri.ex_gw_port = ri.router['gw_port']
+ del ri.router['gw_port']
+ ri.fip_ns = None
+ nat = ri.iptables_manager.ipv4['nat']
+ nat.clear_rules_by_tag = mock.Mock()
+ nat.add_rule = mock.Mock()
+
+ ri.fip_ns = agent.get_fip_ns(external_net_id)
+ subnet_id = _uuid()
+ ri.fip_ns.agent_gateway_port = {
+ 'fixed_ips': [{
+ 'ip_address': '20.0.0.30',
+ 'prefixlen': 24,
+ 'subnet_id': subnet_id
+ }],
+ 'subnets': [{'id': subnet_id,
+ 'cidr': '20.0.0.0/24',
+ 'gateway_ip': '20.0.0.1'}],
+ 'id': _uuid(),
+ 'network_id': external_net_id,
+ 'mac_address': 'ca:fe:de:ad:be:ef'}
+
+ 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 = [
+ l3_test_common.FakeDev(ri.fip_ns.get_ext_device_name(_uuid()))]
+ self.mock_ip_dev.addr.list.return_value = [
+ {'cidr': vm_floating_ip + '/32'},
+ {'cidr': '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')
+++ /dev/null
-# Copyright (c) 2015 Openstack Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import mock
-import netaddr
-
-from neutron.agent.l3 import dvr_router
-from neutron.agent.l3 import link_local_allocator as lla
-from neutron.agent.l3 import router_info
-from neutron.agent.linux import ip_lib
-from neutron.common import constants as l3_constants
-from neutron.common import utils as common_utils
-from neutron.openstack.common import uuidutils
-from neutron.tests import base
-
-_uuid = uuidutils.generate_uuid
-FIP_PRI = 32768
-HOSTNAME = 'myhost'
-
-
-class TestDvrRouterOperations(base.BaseTestCase):
- def setUp(self):
- super(TestDvrRouterOperations, self).setUp()
-
- def _create_router(self, router=None, **kwargs):
- agent_conf = mock.Mock()
- self.router_id = _uuid()
- if not router:
- router = mock.MagicMock()
- return dvr_router.DvrRouter(mock.sentinel.agent,
- mock.sentinel.myhost,
- self.router_id,
- router,
- agent_conf,
- mock.sentinel.interface_driver,
- **kwargs)
-
- def test_get_floating_ips_dvr(self):
- router = mock.MagicMock()
- router.get.return_value = [{'host': mock.sentinel.myhost},
- {'host': mock.sentinel.otherhost}]
- ri = self._create_router(router)
-
- fips = ri.get_floating_ips()
-
- self.assertEqual([{'host': mock.sentinel.myhost}], fips)
-
- @mock.patch.object(ip_lib, 'send_ip_addr_adv_notif')
- @mock.patch.object(ip_lib, 'IPDevice')
- @mock.patch.object(ip_lib, 'IPRule')
- def test_floating_ip_added_dist(self, mIPRule, mIPDevice, mock_adv_notif):
- router = mock.MagicMock()
- ri = self._create_router(router)
- ext_net_id = _uuid()
- subnet_id = _uuid()
- agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30',
- 'prefixlen': 24,
- 'subnet_id': subnet_id}],
- 'subnets': [{'id': subnet_id,
- 'cidr': '20.0.0.0/24',
- 'gateway_ip': '20.0.0.1'}],
- 'id': _uuid(),
- 'network_id': ext_net_id,
- 'mac_address': 'ca:fe:de:ad:be:ef'}
-
- fip = {'id': _uuid(),
- 'host': HOSTNAME,
- 'floating_ip_address': '15.1.2.3',
- 'fixed_ip_address': '192.168.0.1',
- 'floating_network_id': ext_net_id,
- 'port_id': _uuid()}
- ri.fip_ns = mock.Mock()
- ri.fip_ns.agent_gateway_port = agent_gw_port
- ri.fip_ns.allocate_rule_priority.return_value = FIP_PRI
- ri.rtr_fip_subnet = lla.LinkLocalAddressPair('169.254.30.42/31')
- 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('192.168.0.1', 16, FIP_PRI)
- self.assertEqual(1, ri.dist_fip_count)
- # TODO(mrsmith): add more asserts
-
- @mock.patch.object(ip_lib, 'IPWrapper')
- @mock.patch.object(ip_lib, 'IPDevice')
- @mock.patch.object(ip_lib, 'IPRule')
- def test_floating_ip_removed_dist(self, mIPRule, mIPDevice, mIPWrapper):
- router = mock.MagicMock()
- ri = self._create_router(router)
-
- subnet_id = _uuid()
- agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30',
- 'prefixlen': 24,
- 'subnet_id': subnet_id}],
- 'subnets': [{'id': subnet_id,
- 'cidr': '20.0.0.0/24',
- 'gateway_ip': '20.0.0.1'}],
- 'id': _uuid(),
- '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
- ri.fip_2_rtr = '11.22.33.42'
- ri.rtr_2_fip = '11.22.33.40'
- ri.fip_ns.agent_gateway_port = agent_gw_port
- s = lla.LinkLocalAddressPair('169.254.30.42/31')
- ri.rtr_fip_subnet = s
- ri.floating_ip_removed_dist(fip_cidr)
- mIPRule().rule.delete.assert_called_with(
- str(netaddr.IPNetwork(fip_cidr).ip), 16, FIP_PRI)
- mIPDevice().route.delete_route.assert_called_with(fip_cidr, str(s.ip))
- self.assertFalse(ri.fip_ns.unsubscribe.called)
-
- ri.dist_fip_count = 1
- ri.rtr_fip_subnet = lla.LinkLocalAddressPair('15.1.2.3/32')
- _, fip_to_rtr = ri.rtr_fip_subnet.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']))
- mIPDevice().route.delete_gateway.assert_called_once_with(
- str(fip_to_rtr.ip), table=16)
- fip_ns.unsubscribe.assert_called_once_with(ri.router_id)
-
- def _test_add_floating_ip(self, ri, fip, is_failure):
- ri._add_fip_addr_to_device = mock.Mock(return_value=is_failure)
- ri.floating_ip_added_dist = mock.Mock()
-
- result = ri.add_floating_ip(fip,
- mock.sentinel.interface_name,
- mock.sentinel.device)
- ri._add_fip_addr_to_device.assert_called_once_with(
- fip, mock.sentinel.device)
- return result
-
- def test_add_floating_ip(self):
- ri = self._create_router(mock.MagicMock())
- ip = '15.1.2.3'
- fip = {'floating_ip_address': ip}
- result = self._test_add_floating_ip(ri, fip, True)
- ri.floating_ip_added_dist.assert_called_once_with(fip, ip + '/32')
- self.assertEqual(l3_constants.FLOATINGIP_STATUS_ACTIVE, result)
-
- def test_add_floating_ip_error(self):
- ri = self._create_router(mock.MagicMock())
- result = self._test_add_floating_ip(
- ri, {'floating_ip_address': '15.1.2.3'}, False)
- self.assertFalse(ri.floating_ip_added_dist.called)
- self.assertEqual(l3_constants.FLOATINGIP_STATUS_ERROR, result)
-
- @mock.patch.object(router_info.RouterInfo, 'remove_floating_ip')
- def test_remove_floating_ip(self, super_remove_floating_ip):
- ri = self._create_router(mock.MagicMock())
- ri.floating_ip_removed_dist = mock.Mock()
-
- ri.remove_floating_ip(mock.sentinel.device, mock.sentinel.ip_cidr)
-
- super_remove_floating_ip.assert_called_once_with(
- mock.sentinel.device, mock.sentinel.ip_cidr)
- ri.floating_ip_removed_dist.assert_called_once_with(
- mock.sentinel.ip_cidr)
-
- def test__get_internal_port(self):
- ri = self._create_router()
- port = {'fixed_ips': [{'subnet_id': mock.sentinel.subnet_id}]}
- router_ports = [port]
- ri.router.get.return_value = router_ports
- self.assertEqual(port, ri._get_internal_port(mock.sentinel.subnet_id))
-
- def test__get_internal_port_not_found(self):
- ri = self._create_router()
- port = {'fixed_ips': [{'subnet_id': mock.sentinel.subnet_id}]}
- router_ports = [port]
- ri.router.get.return_value = router_ports
- self.assertEqual(None, ri._get_internal_port(mock.sentinel.subnet_id2))
-
- def test__get_snat_idx_ipv4(self):
- ip_cidr = '101.12.13.00/24'
- ri = self._create_router(mock.MagicMock())
- snat_idx = ri._get_snat_idx(ip_cidr)
- # 0x650C0D00 is numerical value of 101.12.13.00
- self.assertEqual(0x650C0D00, snat_idx)
-
- def test__get_snat_idx_ipv6(self):
- ip_cidr = '2620:0:a03:e100::/64'
- ri = self._create_router(mock.MagicMock())
- snat_idx = ri._get_snat_idx(ip_cidr)
- # 0x3D345705 is 30 bit xor folded crc32 of the ip_cidr
- self.assertEqual(0x3D345705, snat_idx)
-
- def test__get_snat_idx_ipv6_below_32768(self):
- ip_cidr = 'd488::/30'
- # crc32 of this ip_cidr is 0x1BD7
- ri = self._create_router(mock.MagicMock())
- snat_idx = ri._get_snat_idx(ip_cidr)
- # 0x1BD7 + 0x3FFFFFFF = 0x40001BD6
- self.assertEqual(0x40001BD6, snat_idx)