}
if router.get('distributed'):
+ kwargs['host'] = self.host
return dvr_router.DvrRouter(*args, **kwargs)
if router.get('ha'):
prefix=INTERNAL_DEV_PREFIX)
def _process_external_gateway(self, ri):
- ex_gw_port = self._get_ex_gw_port(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'])
ri.perform_snat_action(self._handle_router_snat_rules,
interface_name)
- def _put_fips_in_error_state(self, ri):
- fip_statuses = {}
- for fip in ri.router.get(l3_constants.FLOATINGIP_KEY, []):
- fip_statuses[fip['id']] = l3_constants.FLOATINGIP_STATUS_ERROR
- return fip_statuses
-
- def _process_snat_dnat_for_fip(self, ri):
- try:
- self.process_router_floating_ip_nat_rules(ri)
- except Exception:
- # TODO(salv-orlando): Less broad catching
- raise n_exc.FloatingIpSetupException('L3 agent failure to setup '
- 'NAT for floating IPs')
-
- def _configure_fip_addresses(self, ri, interface_name):
- try:
- return self.process_router_floating_ip_addresses(
- ri, interface_name)
- except Exception:
- # TODO(salv-orlando): Less broad catching
- raise n_exc.FloatingIpSetupException('L3 agent failure to setup '
- 'floating IPs')
-
def _update_fip_statuses(self, ri, existing_floating_ips, fip_statuses):
# Identify floating IPs which were disabled
ri.floating_ips = set(fip_statuses.keys())
try:
with ri.iptables_manager.defer_apply():
self._process_external_gateway(ri)
- ex_gw_port = self._get_ex_gw_port(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:
existing_floating_ips = ri.floating_ips
if ri.router['distributed']:
self.create_dvr_fip_interfaces(ri, ex_gw_port)
- self._process_snat_dnat_for_fip(ri)
+ 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 = self._configure_fip_addresses(ri, interface_name)
+ 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 = self._put_fips_in_error_state(ri)
+ fip_statuses = ri.put_fips_in_error_state()
self._update_fip_statuses(ri, existing_floating_ips, fip_statuses)
# TODO(mrsmith) - we shouldn't need to check here
if 'distributed' not in ri.router:
ri.router['distributed'] = False
- ex_gw_port = self._get_ex_gw_port(ri)
+ ex_gw_port = ri.get_ex_gw_port()
if ri.router.get('distributed') and ex_gw_port:
ri.fip_ns = self.get_fip_ns(ex_gw_port['network_id'])
ri.fip_ns.scan_fip_ports(ri)
break
iptables_manager.apply()
- def process_router_floating_ip_nat_rules(self, ri):
- """Configure NAT rules for the router's floating IPs.
-
- Configures iptables rules for the floating ips of the given router
- """
- # Clear out all iptables rules for floating ips
- ri.iptables_manager.ipv4['nat'].clear_rules_by_tag('floating_ip')
-
- floating_ips = self.get_floating_ips(ri)
- # Loop once to ensure that floating ips are configured.
- for fip in floating_ips:
- # Rebuild iptables rules for the floating ip.
- fixed = fip['fixed_ip_address']
- fip_ip = fip['floating_ip_address']
- for chain, rule in self.floating_forward_rules(fip_ip, fixed):
- ri.iptables_manager.ipv4['nat'].add_rule(chain, rule,
- tag='floating_ip')
-
- ri.iptables_manager.apply()
-
def create_dvr_fip_interfaces(self, ri, ex_gw_port):
- floating_ips = self.get_floating_ips(ri)
+ floating_ips = ri.get_floating_ips()
fip_agent_port = self.get_floating_agent_gw_interface(
ri, ex_gw_port['network_id'])
LOG.debug("FloatingIP agent gateway port received from the plugin: "
else:
return self.get_external_device_name(ex_gw_port['id'])
- def _add_floating_ip(self, ri, fip, interface_name, device):
- fip_ip = fip['floating_ip_address']
- ip_cidr = common_utils.ip_to_cidr(fip_ip)
-
- if ri.is_ha:
- ri._add_vip(ip_cidr, interface_name)
- else:
- net = netaddr.IPNetwork(ip_cidr)
- try:
- device.addr.add(net.version, ip_cidr, str(net.broadcast))
- except RuntimeError:
- # any exception occurred here should cause the floating IP
- # to be set in error state
- LOG.warn(_LW("Unable to configure IP address for "
- "floating IP: %s"), fip['id'])
- return l3_constants.FLOATINGIP_STATUS_ERROR
- if ri.router['distributed']:
- # Special Handling for DVR - update FIP namespace
- # and ri.namespace to handle DVR based FIP
- ri.floating_ip_added_dist(fip, ip_cidr)
- else:
- # As GARP is processed in a distinct thread the call below
- # won't raise an exception to be handled.
- ip_lib.send_gratuitous_arp(ri.ns_name,
- interface_name,
- fip_ip,
- self.conf.send_arp_for_ha)
- return l3_constants.FLOATINGIP_STATUS_ACTIVE
-
- def _remove_floating_ip(self, ri, device, ip_cidr):
- if ri.is_ha:
- ri._remove_vip(ip_cidr)
- else:
- net = netaddr.IPNetwork(ip_cidr)
- device.addr.delete(net.version, ip_cidr)
- self.driver.delete_conntrack_state(namespace=ri.ns_name,
- ip=ip_cidr)
- if ri.router['distributed']:
- ri.floating_ip_removed_dist(ip_cidr)
-
- def _get_router_cidrs(self, ri, device):
- if ri.is_ha:
- return set(ri._ha_get_existing_cidrs(device.name))
- else:
- return set([addr['cidr'] for addr in device.addr.list()])
-
- def process_router_floating_ip_addresses(self, ri, interface_name):
- """Configure IP addresses on router's external gateway interface.
-
- Ensures addresses for existing floating IPs and cleans up
- those that should not longer be configured.
- """
-
- fip_statuses = {}
- if interface_name is None:
- LOG.debug('No Interface for floating IPs router: %s',
- ri.router['id'])
- return fip_statuses
-
- device = ip_lib.IPDevice(interface_name, namespace=ri.ns_name)
- existing_cidrs = self._get_router_cidrs(ri, device)
- new_cidrs = set()
-
- floating_ips = self.get_floating_ips(ri)
- # Loop once to ensure that floating ips are configured.
- for fip in floating_ips:
- fip_ip = fip['floating_ip_address']
- ip_cidr = common_utils.ip_to_cidr(fip_ip)
- new_cidrs.add(ip_cidr)
- fip_statuses[fip['id']] = l3_constants.FLOATINGIP_STATUS_ACTIVE
- if ip_cidr not in existing_cidrs:
- fip_statuses[fip['id']] = self._add_floating_ip(
- ri, fip, interface_name, device)
-
- fips_to_remove = (
- ip_cidr for ip_cidr in existing_cidrs - new_cidrs
- if common_utils.is_cidr_host(ip_cidr))
- for ip_cidr in fips_to_remove:
- self._remove_floating_ip(ri, device, ip_cidr)
-
- return fip_statuses
-
- def _get_ex_gw_port(self, ri):
- return ri.router.get('gw_port')
-
def get_internal_device_name(self, port_id):
return (INTERNAL_DEV_PREFIX + port_id)[:self.driver.DEV_NAME_LEN]
def get_router_id(self, ns_name):
return ns_name[len(NS_PREFIX):]
- def get_floating_ips(self, ri):
- """Filter Floating IPs to be hosted on this agent."""
- floating_ips = ri.router.get(l3_constants.FLOATINGIP_KEY, [])
- if ri.router['distributed']:
- floating_ips = [i for i in floating_ips if i['host'] == self.host]
- return floating_ips
-
def get_floating_agent_gw_interface(self, ri, ext_net_id):
"""Filter Floating Agent GW port for the external network."""
fip_ports = ri.router.get(l3_constants.FLOATINGIP_AGENT_INTF_KEY, [])
# 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(ri)
+ floating_ips = ri.get_floating_ips()
preserve_ips = [common_utils.ip_to_cidr(ip['floating_ip_address'])
for ip in floating_ips]
return
else:
ns_name = ri.ns_name
- floating_ips = self.get_floating_ips(ri)
+ floating_ips = ri.get_floating_ips()
preserve_ips = [common_utils.ip_to_cidr(ip['floating_ip_address'])
for ip in floating_ips]
def external_gateway_removed(self, ri, ex_gw_port, interface_name):
if ri.router['distributed']:
- self.process_router_floating_ip_nat_rules(ri)
+ # 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))
- self.process_router_floating_ip_addresses(
- ri, to_fip_interface_name)
+ ri.process_floating_ip_addresses(to_fip_interface_name)
for p in ri.internal_ports:
internal_interface = self.get_internal_device_name(p['id'])
self._snat_redirect_remove(ri, p, internal_interface)
ri._ha_disable_addressing_on_interface(interface_name)
ri._add_vip(internal_cidr, interface_name)
- ex_gw_port = self._get_ex_gw_port(ri)
+ ex_gw_port = ri.get_ex_gw_port()
if ri.router['distributed'] and ex_gw_port:
snat_ports = self.get_snat_interfaces(ri)
sn_port = self._map_internal_interfaces(ri, port, snat_ports)
self.driver.unplug(interface_name, namespace=ri.ns_name,
prefix=INTERNAL_DEV_PREFIX)
- def floating_forward_rules(self, floating_ip, fixed_ip):
- return [('PREROUTING', '-d %s -j DNAT --to %s' %
- (floating_ip, fixed_ip)),
- ('OUTPUT', '-d %s -j DNAT --to %s' %
- (floating_ip, fixed_ip)),
- ('float-snat', '-s %s -j SNAT --to %s' %
- (fixed_ip, floating_ip))]
-
def router_deleted(self, context, router_id):
"""Deal with router deletion RPC message."""
LOG.debug('Got router deleted notification for %s', router_id)
router_infos = self.router_info.values()
num_routers = len(router_infos)
for ri in router_infos:
- ex_gw_port = self._get_ex_gw_port(ri)
+ ex_gw_port = ri.get_ex_gw_port()
if ex_gw_port:
num_ex_gw_ports += 1
num_interfaces += len(ri.router.get(l3_constants.INTERFACE_KEY,
from neutron.agent.l3 import dvr_fip_ns
from neutron.agent.l3 import router_info as router
from neutron.agent.linux import ip_lib
+from neutron.common import constants as l3_constants
+from neutron.common import utils as common_utils
class DvrRouter(router.RouterInfo):
- def __init__(self, *args, **kwargs):
+ def __init__(self, host, *args, **kwargs):
super(DvrRouter, self).__init__(*args, **kwargs)
+ self.host = host
+
self.floating_ips_dict = {}
self.snat_iptables_manager = None
# Linklocal subnet for router and floating IP namespace link
self.rtr_fip_subnet = None
self.dist_fip_count = None
+ def get_floating_ips(self):
+ """Filter Floating IPs to be hosted on this agent."""
+ floating_ips = super(DvrRouter, self).get_floating_ips()
+ return [i for i in floating_ips if i['host'] == self.host]
+
def _handle_fip_nat_rules(self, interface_name, action):
"""Configures NAT rules for Floating IPs for DVR.
# semaphore to sync creation/deletion of this namespace.
self.fip_ns.destroy()
self.fip_ns = None
+
+ def add_floating_ip(self, fip, interface_name, device):
+ if not self._add_fip_addr_to_device(fip, device):
+ return l3_constants.FLOATINGIP_STATUS_ERROR
+
+ # Special Handling for DVR - update FIP namespace
+ # and ri.namespace to handle DVR based FIP
+ ip_cidr = common_utils.ip_to_cidr(fip['floating_ip_address'])
+ self.floating_ip_added_dist(fip, ip_cidr)
+ return l3_constants.FLOATINGIP_STATUS_ACTIVE
+
+ def remove_floating_ip(self, device, ip_cidr):
+ super(DvrRouter, self).remove_floating_ip(device, ip_cidr)
+ self.floating_ip_removed_dist(ip_cidr)
from neutron.agent.linux import ip_lib
from neutron.agent.linux import keepalived
from neutron.agent.metadata import driver as metadata_driver
+from neutron.common import utils as common_utils
from neutron.openstack.common import log as logging
LOG = logging.getLogger(__name__)
instance = self._get_keepalived_instance()
return instance.get_existing_vip_ip_addresses(interface_name)
+ 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)
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)
+ self._add_vip(ip_cidr, interface_name)
+ # TODO(Carl) Should this return status?
+ # return l3_constants.FLOATINGIP_STATUS_ACTIVE
+
+ def remove_floating_ip(self, device, ip_cidr):
+ self._remove_vip(ip_cidr)
# under the License.
from neutron.agent.l3 import router_info as router
+from neutron.agent.linux import ip_lib
+from neutron.common import constants as l3_constants
class LegacyRouter(router.RouterInfo):
- pass
+ def add_floating_ip(self, fip, interface_name, device):
+ if not self._add_fip_addr_to_device(fip, device):
+ return l3_constants.FLOATINGIP_STATUS_ERROR
+
+ # As GARP is processed in a distinct thread the call below
+ # won't raise an exception to be handled.
+ ip_lib.send_gratuitous_arp(self.ns_name,
+ interface_name,
+ fip['floating_ip_address'],
+ self.agent_conf.send_arp_for_ha)
+ return l3_constants.FLOATINGIP_STATUS_ACTIVE
# License for the specific language governing permissions and limitations
# under the License.
+import netaddr
+
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 as n_exc
from neutron.common import utils as common_utils
+from neutron.i18n import _LW
from neutron.openstack.common import log as logging
LOG = logging.getLogger(__name__)
LOG.debug("Removed route entry is '%s'", route)
self._update_routing_table('delete', route)
self.routes = new_routes
+
+ def get_ex_gw_port(self):
+ return self.router.get('gw_port')
+
+ def get_floating_ips(self):
+ """Filter Floating IPs to be hosted on this agent."""
+ return self.router.get(l3_constants.FLOATINGIP_KEY, [])
+
+ def floating_forward_rules(self, floating_ip, fixed_ip):
+ return [('PREROUTING', '-d %s -j DNAT --to %s' %
+ (floating_ip, fixed_ip)),
+ ('OUTPUT', '-d %s -j DNAT --to %s' %
+ (floating_ip, fixed_ip)),
+ ('float-snat', '-s %s -j SNAT --to %s' %
+ (fixed_ip, floating_ip))]
+
+ def process_floating_ip_nat_rules(self):
+ """Configure NAT rules for the router's floating IPs.
+
+ Configures iptables rules for the floating ips of the given router
+ """
+ # Clear out all iptables rules for floating ips
+ self.iptables_manager.ipv4['nat'].clear_rules_by_tag('floating_ip')
+
+ floating_ips = self.get_floating_ips()
+ # Loop once to ensure that floating ips are configured.
+ for fip in floating_ips:
+ # Rebuild iptables rules for the floating ip.
+ fixed = fip['fixed_ip_address']
+ fip_ip = fip['floating_ip_address']
+ for chain, rule in self.floating_forward_rules(fip_ip, fixed):
+ self.iptables_manager.ipv4['nat'].add_rule(chain, rule,
+ tag='floating_ip')
+
+ self.iptables_manager.apply()
+
+ def process_snat_dnat_for_fip(self):
+ try:
+ self.process_floating_ip_nat_rules()
+ except Exception:
+ # TODO(salv-orlando): Less broad catching
+ raise n_exc.FloatingIpSetupException(
+ 'L3 agent failure to setup NAT for floating IPs')
+
+ def _add_fip_addr_to_device(self, fip, device):
+ """Configures the floating ip address on the device.
+ """
+ try:
+ ip_cidr = common_utils.ip_to_cidr(fip['floating_ip_address'])
+ net = netaddr.IPNetwork(ip_cidr)
+ device.addr.add(net.version, ip_cidr, str(net.broadcast))
+ return True
+ except RuntimeError:
+ # any exception occurred here should cause the floating IP
+ # to be set in error state
+ LOG.warn(_LW("Unable to configure IP address for "
+ "floating IP: %s"), fip['id'])
+
+ def add_floating_ip(self, fip, interface_name, device):
+ raise NotImplementedError()
+
+ def remove_floating_ip(self, device, ip_cidr):
+ net = netaddr.IPNetwork(ip_cidr)
+ device.addr.delete(net.version, ip_cidr)
+ self.driver.delete_conntrack_state(namespace=self.ns_name, ip=ip_cidr)
+
+ def get_router_cidrs(self, device):
+ return set([addr['cidr'] for addr in device.addr.list()])
+
+ def process_floating_ip_addresses(self, interface_name):
+ """Configure IP addresses on router's external gateway interface.
+
+ Ensures addresses for existing floating IPs and cleans up
+ those that should not longer be configured.
+ """
+
+ fip_statuses = {}
+ if interface_name is None:
+ LOG.debug('No Interface for floating IPs router: %s',
+ self.router['id'])
+ return fip_statuses
+
+ device = ip_lib.IPDevice(interface_name, namespace=self.ns_name)
+ existing_cidrs = self.get_router_cidrs(device)
+ new_cidrs = set()
+
+ floating_ips = self.get_floating_ips()
+ # Loop once to ensure that floating ips are configured.
+ for fip in floating_ips:
+ fip_ip = fip['floating_ip_address']
+ ip_cidr = common_utils.ip_to_cidr(fip_ip)
+ new_cidrs.add(ip_cidr)
+ fip_statuses[fip['id']] = l3_constants.FLOATINGIP_STATUS_ACTIVE
+ if ip_cidr not in existing_cidrs:
+ fip_statuses[fip['id']] = self.add_floating_ip(
+ fip, interface_name, device)
+
+ fips_to_remove = (
+ ip_cidr for ip_cidr in existing_cidrs - new_cidrs
+ if common_utils.is_cidr_host(ip_cidr))
+ for ip_cidr in fips_to_remove:
+ self.remove_floating_ip(device, ip_cidr)
+
+ return fip_statuses
+
+ def configure_fip_addresses(self, interface_name):
+ try:
+ return self.process_floating_ip_addresses(interface_name)
+ except Exception:
+ # TODO(salv-orlando): Less broad catching
+ raise n_exc.FloatingIpSetupException('L3 agent failure to setup '
+ 'floating IPs')
+
+ def put_fips_in_error_state(self):
+ fip_statuses = {}
+ for fip in self.router.get(l3_constants.FLOATINGIP_KEY, []):
+ fip_statuses[fip['id']] = l3_constants.FLOATINGIP_STATUS_ERROR
+ return fip_statuses
router_id = router.router_id
ha_device_name = router.get_ha_device_name(router.ha_port['id'])
ha_device_cidr = router.ha_port['ip_cidr']
- external_port = self.agent._get_ex_gw_port(router)
+ 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(
internal_port['id'])
internal_device_cidr = internal_port['ip_cidr']
floating_ip_cidr = common_utils.ip_to_cidr(
- self.agent.get_floating_ips(router)[0]['floating_ip_address'])
+ router.get_floating_ips()[0]['floating_ip_address'])
default_gateway_ip = external_port['subnet'].get('gateway_ip')
return """vrrp_instance VR_1 {
self.assertIn(new_fip, new_config)
self.assertNotIn(old_gw, new_config)
self.assertIn(new_gw, new_config)
- external_port = self.agent._get_ex_gw_port(router)
+ external_port = router.get_ex_gw_port()
external_device_name = self.agent.get_external_device_name(
external_port['id'])
self.assertNotIn('%s/24 dev %s' %
router = self.manage_router(self.agent, router_info)
if enable_ha:
- port = self.agent._get_ex_gw_port(router)
+ port = router.get_ex_gw_port()
interface_name = self.agent.get_external_device_name(port['id'])
self._assert_no_ip_addresses_on_interface(router, interface_name)
helpers.wait_until_true(lambda: router.ha_state == 'master')
self.assertFalse(router.keepalived_manager.process.active)
def _assert_external_device(self, router):
- external_port = self.agent._get_ex_gw_port(router)
+ external_port = router.get_ex_gw_port()
self.assertTrue(self.device_exists_with_ip_mac(
external_port, self.agent.get_external_device_name,
router.ns_name))
def _assert_gateway(self, router):
- external_port = self.agent._get_ex_gw_port(router)
+ external_port = router.get_ex_gw_port()
external_device_name = self.agent.get_external_device_name(
external_port['id'])
external_device = ip_lib.IPDevice(external_device_name,
def _floating_ips_configured(self, router):
floating_ips = router.router[l3_constants.FLOATINGIP_KEY]
- external_port = self.agent._get_ex_gw_port(router)
+ 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']),
'%s/32' % fip['floating_ip_address'],
]
def _assert_dvr_external_device(self, router):
- external_port = self.agent._get_ex_gw_port(router)
+ external_port = router.get_ex_gw_port()
snat_ns_name = self.agent.get_snat_ns_name(router.router_id)
# if the agent is in dvr_snat mode, then we have to check
def _assert_dvr_snat_gateway(self, router):
namespace = self.agent.get_snat_ns_name(router.router_id)
- external_port = self.agent._get_ex_gw_port(router)
+ external_port = router.get_ex_gw_port()
external_device_name = self.agent.get_external_device_name(
external_port['id'])
external_device = ip_lib.IPDevice(external_device_name,
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
def _create_router(self, router, **kwargs):
agent_conf = mock.Mock()
- return dvr_router.DvrRouter(mock.sentinel.router_id,
+ return dvr_router.DvrRouter(mock.sentinel.myhost,
+ mock.sentinel.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_garp_for_proxyarp')
@mock.patch.object(ip_lib, 'IPDevice')
@mock.patch.object(ip_lib, 'IpRule')
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)
--- /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
+
+from neutron.agent.l3 import ha_router
+from neutron.tests import base
+
+
+class TestBasicRouterOperations(base.BaseTestCase):
+ def setUp(self):
+ super(TestBasicRouterOperations, self).setUp()
+
+ def _create_router(self, router=None, **kwargs):
+ if not router:
+ router = mock.MagicMock()
+ return ha_router.HaRouter(mock.sentinel.router_id,
+ router,
+ mock.sentinel.agent_conf,
+ mock.sentinel.driver,
+ ns_name=mock.sentinel.namespace,
+ **kwargs)
+
+ def test_get_router_cidrs_returns_ha_cidrs(self):
+ ri = self._create_router()
+ device = mock.MagicMock()
+ device.name.return_value = 'eth2'
+ addresses = ['15.1.2.2/24', '15.1.2.3/32']
+ ri._ha_get_existing_cidrs = mock.MagicMock(return_value=addresses)
+ self.assertEqual(set(addresses), ri.get_router_cidrs(device))
--- /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
+
+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 exceptions as n_exc
+from neutron.openstack.common import uuidutils
+from neutron.tests import base
+
+_uuid = uuidutils.generate_uuid
+
+
+class BasicRouterTestCaseFramework(base.BaseTestCase):
+ def _create_router(self, router=None, **kwargs):
+ if not router:
+ router = mock.MagicMock()
+ return router_info.RouterInfo(mock.sentinel.router_id,
+ router,
+ mock.sentinel.agent_conf,
+ mock.sentinel.interface_driver,
+ **kwargs)
+
+
+class TestBasicRouterOperations(BasicRouterTestCaseFramework):
+
+ def test_get_floating_ips(self):
+ router = mock.MagicMock()
+ router.get.return_value = [mock.sentinel.floating_ip]
+ ri = self._create_router(router)
+
+ fips = ri.get_floating_ips()
+
+ self.assertEqual([mock.sentinel.floating_ip], fips)
+
+ def test_process_floating_ip_nat_rules(self):
+ ri = self._create_router()
+ fips = [{'fixed_ip_address': mock.sentinel.ip,
+ 'floating_ip_address': mock.sentinel.fip}]
+ ri.get_floating_ips = mock.Mock(return_value=fips)
+ ri.iptables_manager = mock.MagicMock()
+ ipv4_nat = ri.iptables_manager.ipv4['nat']
+ ri.floating_forward_rules = mock.Mock(
+ return_value=[(mock.sentinel.chain, mock.sentinel.rule)])
+
+ ri.process_floating_ip_nat_rules()
+
+ # Be sure that the rules are cleared first and apply is called last
+ self.assertEqual(mock.call.clear_rules_by_tag('floating_ip'),
+ ipv4_nat.mock_calls[0])
+ self.assertEqual(mock.call.apply(), ri.iptables_manager.mock_calls[-1])
+
+ # Be sure that add_rule is called somewhere in the middle
+ ipv4_nat.add_rule.assert_called_once_with(mock.sentinel.chain,
+ mock.sentinel.rule,
+ tag='floating_ip')
+
+ def test_process_floating_ip_nat_rules_removed(self):
+ ri = self._create_router()
+ ri.get_floating_ips = mock.Mock(return_value=[])
+ ri.iptables_manager = mock.MagicMock()
+ ipv4_nat = ri.iptables_manager.ipv4['nat']
+
+ ri.process_floating_ip_nat_rules()
+
+ # Be sure that the rules are cleared first and apply is called last
+ self.assertEqual(mock.call.clear_rules_by_tag('floating_ip'),
+ ipv4_nat.mock_calls[0])
+ self.assertEqual(mock.call.apply(), ri.iptables_manager.mock_calls[-1])
+
+ # Be sure that add_rule is called somewhere in the middle
+ self.assertFalse(ipv4_nat.add_rule.called)
+
+ def _test_add_fip_addr_to_device_error(self, device):
+ ri = self._create_router()
+ ip = '15.1.2.3'
+
+ result = ri._add_fip_addr_to_device(
+ {'id': mock.sentinel.id, 'floating_ip_address': ip}, device)
+
+ device.addr.add.assert_called_with(4, ip + '/32', ip)
+ return result
+
+ def test__add_fip_addr_to_device(self):
+ result = self._test_add_fip_addr_to_device_error(mock.Mock())
+ self.assertTrue(result)
+
+ def test__add_fip_addr_to_device_error(self):
+ device = mock.Mock()
+ device.addr.add.side_effect = RuntimeError
+ result = self._test_add_fip_addr_to_device_error(device)
+ self.assertFalse(result)
+
+ def test_process_snat_dnat_for_fip(self):
+ ri = self._create_router()
+ ri.process_floating_ip_nat_rules = mock.Mock(side_effect=Exception)
+
+ self.assertRaises(n_exc.FloatingIpSetupException,
+ ri.process_snat_dnat_for_fip)
+
+ ri.process_floating_ip_nat_rules.assert_called_once_with()
+
+ def test_put_fips_in_error_state(self):
+ ri = self._create_router()
+ ri.router = mock.Mock()
+ ri.router.get.return_value = [{'id': mock.sentinel.id1},
+ {'id': mock.sentinel.id2}]
+
+ statuses = ri.put_fips_in_error_state()
+
+ expected = [{mock.sentinel.id1: l3_constants.FLOATINGIP_STATUS_ERROR,
+ mock.sentinel.id2: l3_constants.FLOATINGIP_STATUS_ERROR}]
+ self.assertNotEqual(expected, statuses)
+
+ def test_configure_fip_addresses(self):
+ ri = self._create_router()
+ ri.process_floating_ip_addresses = mock.Mock(
+ side_effect=Exception)
+
+ self.assertRaises(n_exc.FloatingIpSetupException,
+ ri.configure_fip_addresses,
+ mock.sentinel.interface_name)
+
+ ri.process_floating_ip_addresses.assert_called_once_with(
+ mock.sentinel.interface_name)
+
+ def test_get_router_cidrs_returns_cidrs(self):
+ ri = self._create_router()
+ addresses = ['15.1.2.2/24', '15.1.2.3/32']
+ device = mock.MagicMock()
+ device.addr.list.return_value = [{'cidr': addresses[0]},
+ {'cidr': addresses[1]}]
+ self.assertEqual(set(addresses), ri.get_router_cidrs(device))
+
+
+@mock.patch.object(ip_lib, 'IPDevice')
+class TestFloatingIpWithMockDevice(BasicRouterTestCaseFramework):
+
+ def test_process_floating_ip_addresses_remap(self, IPDevice):
+ fip_id = _uuid()
+ fip = {
+ 'id': fip_id, 'port_id': _uuid(),
+ 'floating_ip_address': '15.1.2.3',
+ 'fixed_ip_address': '192.168.0.2'
+ }
+
+ IPDevice.return_value = device = mock.Mock()
+ device.addr.list.return_value = [{'cidr': '15.1.2.3/32'}]
+ ri = self._create_router()
+ ri.get_floating_ips = mock.Mock(return_value=[fip])
+
+ fip_statuses = ri.process_floating_ip_addresses(
+ mock.sentinel.interface_name)
+ self.assertEqual({fip_id: l3_constants.FLOATINGIP_STATUS_ACTIVE},
+ fip_statuses)
+
+ self.assertFalse(device.addr.add.called)
+ self.assertFalse(device.addr.delete.called)
+
+ def test_process_router_with_disabled_floating_ip(self, IPDevice):
+ fip_id = _uuid()
+ fip = {
+ 'id': fip_id, 'port_id': _uuid(),
+ 'floating_ip_address': '15.1.2.3',
+ 'fixed_ip_address': '192.168.0.2'
+ }
+
+ ri = self._create_router()
+ ri.floating_ips = [fip]
+ ri.get_floating_ips = mock.Mock(return_value=[])
+
+ fip_statuses = ri.process_floating_ip_addresses(
+ mock.sentinel.interface_name)
+
+ self.assertIsNone(fip_statuses.get(fip_id))
+
+ def test_process_router_floating_ip_with_device_add_error(self, IPDevice):
+ IPDevice.return_value = device = mock.Mock(side_effect=RuntimeError)
+ device.addr.list.return_value = []
+ fip_id = _uuid()
+ fip = {
+ 'id': fip_id, 'port_id': _uuid(),
+ 'floating_ip_address': '15.1.2.3',
+ 'fixed_ip_address': '192.168.0.2'
+ }
+ ri = self._create_router()
+ ri.add_floating_ip = mock.Mock(
+ return_value=l3_constants.FLOATINGIP_STATUS_ERROR)
+ ri.get_floating_ips = mock.Mock(return_value=[fip])
+
+ fip_statuses = ri.process_floating_ip_addresses(
+ mock.sentinel.interface_name)
+
+ self.assertEqual({fip_id: l3_constants.FLOATINGIP_STATUS_ERROR},
+ fip_statuses)
+
+ # TODO(mrsmith): refactor for DVR cases
+ def test_process_floating_ip_addresses_remove(self, IPDevice):
+ IPDevice.return_value = device = mock.Mock()
+ device.addr.list.return_value = [{'cidr': '15.1.2.3/32'}]
+
+ ri = self._create_router()
+ ri.remove_floating_ip = mock.Mock()
+ ri.router.get = mock.Mock(return_value=[])
+
+ fip_statuses = ri.process_floating_ip_addresses(
+ mock.sentinel.interface_name)
+ self.assertEqual({}, fip_statuses)
+ ri.remove_floating_ip.assert_called_once_with(device, '15.1.2.3/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
+
+from neutron.agent.l3 import legacy_router
+from neutron.agent.linux import ip_lib
+from neutron.common import constants as l3_constants
+from neutron.tests import base
+
+
+class BasicRouterTestCaseFramework(base.BaseTestCase):
+ def _create_router(self, router=None, **kwargs):
+ if not router:
+ router = mock.MagicMock()
+ self.agent_conf = mock.Mock()
+ self.driver = mock.Mock()
+ return legacy_router.LegacyRouter(mock.sentinel.router_id,
+ router,
+ self.agent_conf,
+ self.driver,
+ ns_name=mock.sentinel.namespace,
+ **kwargs)
+
+
+class TestBasicRouterOperations(BasicRouterTestCaseFramework):
+
+ def test_remove_floating_ip(self):
+ ri = self._create_router(mock.MagicMock())
+ device = mock.Mock()
+ cidr = '15.1.2.3/32'
+
+ ri.remove_floating_ip(device, cidr)
+
+ device.addr.delete.assert_called_once_with(4, cidr)
+ self.driver.delete_conntrack_state.assert_called_once_with(
+ ip=cidr,
+ namespace=mock.sentinel.namespace)
+
+
+@mock.patch.object(ip_lib, 'send_gratuitous_arp')
+class TestAddFloatingIpWithMockGarp(BasicRouterTestCaseFramework):
+ def test_add_floating_ip(self, send_gratuitous_arp):
+ ri = self._create_router()
+ ri._add_fip_addr_to_device = mock.Mock(return_value=True)
+ self.agent_conf.send_arp_for_ha = mock.sentinel.arp_count
+ ri.ns_name = mock.sentinel.ns_name
+ ip = '15.1.2.3'
+ result = ri.add_floating_ip({'floating_ip_address': ip},
+ mock.sentinel.interface_name,
+ mock.sentinel.device)
+ ip_lib.send_gratuitous_arp.assert_called_once_with(
+ mock.sentinel.ns_name,
+ mock.sentinel.interface_name,
+ ip,
+ mock.sentinel.arp_count)
+ self.assertEqual(l3_constants.FLOATINGIP_STATUS_ACTIVE, result)
+
+ def test_add_floating_ip_error(self, send_gratuitous_arp):
+ ri = self._create_router()
+ ri._add_fip_addr_to_device = mock.Mock(return_value=False)
+ result = ri.add_floating_ip({'floating_ip_address': '15.1.2.3'},
+ mock.sentinel.interface_name,
+ mock.sentinel.device)
+ self.assertFalse(ip_lib.send_gratuitous_arp.called)
+ self.assertEqual(l3_constants.FLOATINGIP_STATUS_ERROR, result)
from neutron.agent.l3 import agent as l3_agent
from neutron.agent.l3 import config as l3_config
from neutron.agent.l3 import dvr
-from neutron.agent.l3 import dvr_fip_ns
from neutron.agent.l3 import dvr_router
from neutron.agent.l3 import ha
+from neutron.agent.l3 import legacy_router
from neutron.agent.l3 import link_local_allocator as lla
from neutron.agent.l3 import router_info as l3router
from neutron.agent.linux import external_process
def test_process_dist_router(self):
router = prepare_router_data()
- ri = dvr_router.DvrRouter(router['id'], router, **self.ri_kwargs)
+ ri = dvr_router.DvrRouter(HOSTNAME,
+ router['id'],
+ router,
+ **self.ri_kwargs)
subnet_id = _get_subnet_id(router[l3_constants.INTERFACE_KEY][0])
ri.router['distributed'] = True
ri.router['_snat_router_interfaces'] = [{
agent.host = HOSTNAME
fake_fip_id = 'fake_fip_id'
agent.create_dvr_fip_interfaces = mock.Mock()
- agent.process_router_floating_ip_addresses = mock.Mock()
- agent.process_router_floating_ip_nat_rules = mock.Mock()
- agent.process_router_floating_ip_addresses.return_value = {
+ 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()
'port_id': _uuid(),
'host': HOSTNAME}]}
agent.process_router(ri)
- agent.process_router_floating_ip_addresses.assert_called_with(
- ri, mock.ANY)
- agent.process_router_floating_ip_addresses.reset_mock()
- agent.process_router_floating_ip_nat_rules.assert_called_with(ri)
- agent.process_router_floating_ip_nat_rules.reset_mock()
+ ri.process_floating_ip_addresses.assert_called_with(mock.ANY)
+ 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()
# remap floating IP to a new fixed ip
router[l3_constants.FLOATINGIP_KEY] = fake_floatingips2['floatingips']
agent.process_router(ri)
- agent.process_router_floating_ip_addresses.assert_called_with(
- ri, mock.ANY)
- agent.process_router_floating_ip_addresses.reset_mock()
- agent.process_router_floating_ip_nat_rules.assert_called_with(ri)
- agent.process_router_floating_ip_nat_rules.reset_mock()
+ ri.process_floating_ip_addresses.assert_called_with(mock.ANY)
+ 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()
ri.router['gw_port']['fixed_ips'][0]['ip_address'] = str(old_ip + 1)
agent.process_router(ri)
- agent.process_router_floating_ip_addresses.reset_mock()
- agent.process_router_floating_ip_nat_rules.reset_mock()
+ 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)
# remove just the floating ips
del router[l3_constants.FLOATINGIP_KEY]
agent.process_router(ri)
- agent.process_router_floating_ip_addresses.assert_called_with(
- ri, mock.ANY)
- agent.process_router_floating_ip_addresses.reset_mock()
- agent.process_router_floating_ip_nat_rules.assert_called_with(ri)
- agent.process_router_floating_ip_nat_rules.reset_mock()
+ ri.process_floating_ip_addresses.assert_called_with(mock.ANY)
+ ri.process_floating_ip_addresses.reset_mock()
+ ri.process_floating_ip_nat_rules.assert_called_with()
+ ri.process_floating_ip_nat_rules.reset_mock()
# now no ports so state is torn down
del router[l3_constants.INTERFACE_KEY]
agent.process_router(ri)
self.assertEqual(self.send_arp.call_count, 1)
distributed = ri.router.get('distributed', False)
- self.assertEqual(agent.process_router_floating_ip_addresses.called,
+ self.assertEqual(ri.process_floating_ip_addresses.called,
distributed)
- self.assertEqual(agent.process_router_floating_ip_nat_rules.called,
+ self.assertEqual(ri.process_floating_ip_nat_rules.called,
distributed)
@mock.patch('neutron.agent.linux.ip_lib.IPDevice')
- def _test_process_router_floating_ip_addresses_add(self, ri,
- agent, IPDevice):
- floating_ips = agent.get_floating_ips(ri)
+ def _test_process_floating_ip_addresses_add(self, ri, agent, IPDevice):
+ floating_ips = ri.get_floating_ips()
fip_id = floating_ips[0]['id']
IPDevice.return_value = device = mock.Mock()
device.addr.list.return_value = []
ri.iptables_manager.ipv4['nat'] = mock.MagicMock()
ex_gw_port = {'id': _uuid(), 'network_id': mock.sentinel.ext_net_id}
+ ri.add_floating_ip = mock.Mock(
+ return_value=l3_constants.FLOATINGIP_STATUS_ACTIVE)
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)
- fip_statuses = agent.process_router_floating_ip_addresses(
- ri, ex_gw_port)
+ fip_statuses = ri.process_floating_ip_addresses(
+ mock.sentinel.interface_name)
self.assertEqual({fip_id: l3_constants.FLOATINGIP_STATUS_ACTIVE},
fip_statuses)
- device.addr.add.assert_called_once_with(4, '15.1.2.3/32', '15.1.2.3')
-
- def test_process_router_floating_ip_nat_rules_add(self):
- fip = {
- 'id': _uuid(), 'port_id': _uuid(),
- 'floating_ip_address': '15.1.2.3',
- 'fixed_ip_address': '192.168.0.1'
- }
-
- ri = mock.MagicMock()
- ri.router['distributed'].__nonzero__ = lambda self: False
-
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- agent.get_floating_ips = mock.Mock(return_value=[fip])
-
- agent.process_router_floating_ip_nat_rules(ri)
-
- nat = ri.iptables_manager.ipv4['nat']
- nat.clear_rules_by_tag.assert_called_once_with('floating_ip')
- rules = agent.floating_forward_rules('15.1.2.3', '192.168.0.1')
- for chain, rule in rules:
- nat.add_rule.assert_any_call(chain, rule, tag='floating_ip')
+ 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()
router = prepare_router_data(enable_snat=True)
router[l3_constants.FLOATINGIP_AGENT_INTF_KEY] = agent_gateway_port
router['distributed'] = True
- ri = dvr_router.DvrRouter(router['id'], router, **self.ri_kwargs)
+ ri = dvr_router.DvrRouter(
+ HOSTNAME, router['id'], router, **self.ri_kwargs)
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
self.assertEqual(
agent_gateway_port[0],
router[l3_constants.FLOATINGIP_KEY] = fake_floatingips['floatingips']
router[l3_constants.FLOATINGIP_AGENT_INTF_KEY] = agent_gateway_port
router['distributed'] = True
- ri = dvr_router.DvrRouter(router['id'], router, **self.ri_kwargs)
+ ri = dvr_router.DvrRouter(
+ HOSTNAME, router['id'], router, **self.ri_kwargs)
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
ext_gw_port = ri.router.get('gw_port')
ri.dist_fip_count = 0
ri.fip_ns.subscribe = mock.Mock()
- with contextlib.nested(mock.patch.object(agent,
+ with contextlib.nested(mock.patch.object(ri,
'get_floating_ips'),
mock.patch.object(
agent, 'get_floating_agent_gw_interface'),
router = prepare_router_data(enable_snat=True)
router[l3_constants.FLOATINGIP_KEY] = fake_floatingips['floatingips']
- ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
+ ri = legacy_router.LegacyRouter(router['id'], router, **self.ri_kwargs)
ri.iptables_manager.ipv4['nat'] = mock.MagicMock()
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- self._test_process_router_floating_ip_addresses_add(ri, agent)
+ agent.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': [
router = prepare_router_data(enable_snat=True)
router[l3_constants.FLOATINGIP_KEY] = fake_floatingips['floatingips']
router['distributed'] = True
- ri = dvr_router.DvrRouter(router['id'], router, **self.ri_kwargs)
+ ri = dvr_router.DvrRouter(HOSTNAME,
+ router['id'],
+ router,
+ **self.ri_kwargs)
ri.iptables_manager.ipv4['nat'] = mock.MagicMock()
ri.dist_fip_count = 0
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- agent.host = HOSTNAME
fip_ns = agent.get_fip_ns(mock.sentinel.ext_net_id)
fip_ns.agent_gateway_port = (
{'fixed_ips': [{'ip_address': '20.0.0.30',
'mac_address': 'ca:fe:de:ad:be:ef',
'ip_cidr': '20.0.0.30/24'}
)
- self._test_process_router_floating_ip_addresses_add(ri, agent)
-
- def test_get_router_cidrs_returns_cidrs(self):
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- ri = mock.MagicMock()
- ri.is_ha = False
- addresses = ['15.1.2.2/24', '15.1.2.3/32']
- device = mock.MagicMock()
- device.addr.list.return_value = [{'cidr': addresses[0]},
- {'cidr': addresses[1]}]
- self.assertEqual(set(addresses), agent._get_router_cidrs(ri, device))
-
- def test_get_router_cidrs_returns_ha_cidrs(self):
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- ri = mock.MagicMock()
- ri.is_ha = True
- device = mock.MagicMock()
- device.name.return_value = 'eth2'
- addresses = ['15.1.2.2/24', '15.1.2.3/32']
- ri._ha_get_existing_cidrs = mock.MagicMock()
- ri._ha_get_existing_cidrs.return_value = addresses
- self.assertEqual(set(addresses), agent._get_router_cidrs(ri, device))
-
- # TODO(mrsmith): refactor for DVR cases
- @mock.patch('neutron.agent.linux.ip_lib.IPDevice')
- def test_process_router_floating_ip_addresses_remove(self, IPDevice):
- IPDevice.return_value = device = mock.Mock()
- device.addr.list.return_value = [{'cidr': '15.1.2.3/32'}]
-
- ri = mock.MagicMock()
- ri.router.get.return_value = []
- type(ri).is_ha = mock.PropertyMock(return_value=False)
- ri.router['distributed'].__nonzero__ = lambda self: False
-
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
-
- fip_statuses = agent.process_router_floating_ip_addresses(
- ri, {'id': _uuid()})
- self.assertEqual({}, fip_statuses)
- device.addr.delete.assert_called_once_with(4, '15.1.2.3/32')
- self.mock_driver.delete_conntrack_state.assert_called_once_with(
- namespace=ri.ns_name,
- ip='15.1.2.3/32')
-
- def test_process_router_floating_ip_nat_rules_remove(self):
- ri = mock.MagicMock()
- ri.router.get.return_value = []
-
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
-
- agent.process_router_floating_ip_nat_rules(ri)
-
- nat = ri.iptables_manager.ipv4['nat']
- nat = ri.iptables_manager.ipv4['nat`']
- nat.clear_rules_by_tag.assert_called_once_with('floating_ip')
-
- @mock.patch('neutron.agent.linux.ip_lib.IPDevice')
- def test_process_router_floating_ip_addresses_remap(self, IPDevice):
- fip_id = _uuid()
- fip = {
- 'id': fip_id, 'port_id': _uuid(),
- 'floating_ip_address': '15.1.2.3',
- 'fixed_ip_address': '192.168.0.2'
- }
-
- IPDevice.return_value = device = mock.Mock()
- device.addr.list.return_value = [{'cidr': '15.1.2.3/32'}]
- ri = mock.MagicMock()
- ri.router['distributed'].__nonzero__ = lambda self: False
- type(ri).is_ha = mock.PropertyMock(return_value=False)
- ri.router.get.return_value = [fip]
-
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
-
- fip_statuses = agent.process_router_floating_ip_addresses(
- ri, {'id': _uuid()})
- self.assertEqual({fip_id: l3_constants.FLOATINGIP_STATUS_ACTIVE},
- fip_statuses)
-
- self.assertFalse(device.addr.add.called)
- self.assertFalse(device.addr.delete.called)
-
- @mock.patch('neutron.agent.linux.ip_lib.IPDevice')
- def test_process_router_with_disabled_floating_ip(self, IPDevice):
- fip_id = _uuid()
- fip = {
- 'id': fip_id, 'port_id': _uuid(),
- 'floating_ip_address': '15.1.2.3',
- 'fixed_ip_address': '192.168.0.2'
- }
-
- ri = mock.MagicMock()
- ri.floating_ips = [fip]
- ri.router.get.return_value = []
-
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
-
- fip_statuses = agent.process_router_floating_ip_addresses(
- ri, {'id': _uuid(), 'network_id': mock.sentinel.ext_net_id})
-
- self.assertIsNone(fip_statuses.get(fip_id))
-
- @mock.patch('neutron.agent.linux.ip_lib.IPDevice')
- def test_process_router_floating_ip_with_device_add_error(self, IPDevice):
- IPDevice.return_value = device = mock.Mock()
- device.addr.add.side_effect = RuntimeError()
- device.addr.list.return_value = []
- fip_id = _uuid()
- fip = {
- 'id': fip_id, 'port_id': _uuid(),
- 'floating_ip_address': '15.1.2.3',
- 'fixed_ip_address': '192.168.0.2'
- }
- ri = mock.MagicMock()
- type(ri).is_ha = mock.PropertyMock(return_value=False)
- ri.router.get.return_value = [fip]
- ri.router['distributed'].__nonzero__ = lambda self: False
-
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
-
- fip_statuses = agent.process_router_floating_ip_addresses(
- ri, {'id': _uuid()})
-
- self.assertEqual({fip_id: l3_constants.FLOATINGIP_STATUS_ERROR},
- fip_statuses)
def test_process_router_snat_disabled(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
'fixed_ip_address': '7.7.7.7',
'port_id': router[l3_constants.INTERFACE_KEY][0]['id']}]
- ri = l3router.RouterInfo(router['id'], router, **self.ri_kwargs)
+ ri = legacy_router.LegacyRouter(router['id'],
+ router,
+ **self.ri_kwargs)
agent.external_gateway_added = mock.Mock()
agent.process_router(ri)
# Assess the call for putting the floating IP up was performed
def test_process_router_floatingip_exception(self):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- agent.process_router_floating_ip_addresses = mock.Mock()
- agent.process_router_floating_ip_addresses.side_effect = RuntimeError
with mock.patch.object(
agent.plugin_rpc,
'update_floatingip_statuses') as mock_update_fip_status:
'port_id': router[l3_constants.INTERFACE_KEY][0]['id']}]
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()
agent.process_router(ri)
# Assess the call for putting the floating IP into Error
def test_handle_router_snat_rules_distributed_without_snat_manager(self):
ri = dvr_router.DvrRouter(
+ HOSTNAME,
'foo_router_id',
{'distributed': True},
**self.ri_kwargs)
self.mock_driver.unplug.reset_mock()
external_net_id = router['gw_port']['network_id']
- ri = dvr_router.DvrRouter(router['id'], router, **self.ri_kwargs)
+ ri = dvr_router.DvrRouter(
+ 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, ri.ex_gw_port,
agent.get_external_device_name(ri.ex_gw_port['id']))
- self.assertFalse(nat.add_rule.called)
- nat.clear_rules_by_tag.assert_called_once_with('floating_ip')
if fip_ns:
- self.mock_ip.del_veth.assert_called_once_with(
- fip_ns.get_int_device_name(ri.router['id']))
- self.mock_ip_dev.route.delete_gateway.assert_called_once_with(
- str(fip_to_rtr.ip), table=dvr_fip_ns.FIP_RT_TBL)
-
- self.assertEqual(ri.dist_fip_count, 0)
- self.assertFalse(fip_ns.has_subscribers())
-
- self.assertIsNone(fip_ns.agent_gateway_port)
- self.assertTrue(fip_ns.destroyed)
- self.mock_ip.netns.delete.assert_called_once_with(
- fip_ns.get_name())
- self.assertEqual(self.mock_driver.unplug.call_count, 1)
+ ri.remove_floating_ip.assert_called_once_with(self.mock_ip_dev,
+ '19.4.4.2/32')
else:
- self.assertFalse(self.mock_driver.unplug.called)
+ 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)
if not skip(managed_flag):
assertFlag(managed_flag)('AdvManagedFlag on',
self.utils_replace_file.call_args[0][1])
-
- def test__put_fips_in_error_state(self):
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- ri = mock.Mock()
- ri.router.get.return_value = [{'id': mock.sentinel.id1},
- {'id': mock.sentinel.id2}]
-
- statuses = agent._put_fips_in_error_state(ri)
-
- expected = [{mock.sentinel.id1: l3_constants.FLOATINGIP_STATUS_ERROR,
- mock.sentinel.id2: l3_constants.FLOATINGIP_STATUS_ERROR}]
- self.assertNotEqual(expected, statuses)
-
- def test__process_snat_dnat_for_fip(self):
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- agent.process_router_floating_ip_nat_rules = mock.Mock(
- side_effect=Exception)
-
- self.assertRaises(n_exc.FloatingIpSetupException,
- agent._process_snat_dnat_for_fip,
- mock.sentinel.ri)
-
- agent.process_router_floating_ip_nat_rules.assert_called_with(
- mock.sentinel.ri)
-
- def test__configure_fip_addresses(self):
- agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
- agent.process_router_floating_ip_addresses = mock.Mock(
- side_effect=Exception)
-
- self.assertRaises(n_exc.FloatingIpSetupException,
- agent._configure_fip_addresses,
- mock.sentinel.ri,
- mock.sentinel.ex_gw_port)
-
- agent.process_router_floating_ip_addresses.assert_called_with(
- mock.sentinel.ri,
- mock.sentinel.ex_gw_port)