]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Move DVR floating ip methods to dvr_router
authorCarl Baldwin <carl.baldwin@hp.com>
Tue, 20 Jan 2015 16:48:47 +0000 (16:48 +0000)
committerCarl Baldwin <carl@ecbaldwin.net>
Thu, 5 Feb 2015 23:08:48 +0000 (23:08 +0000)
Change-Id: Ic751d87df2d2fb44683f1dd555e8ed86dff3aeaf
Partially-Implements: bp/restructure-l3-agent

neutron/agent/l3/agent.py
neutron/agent/l3/dvr.py
neutron/agent/l3/dvr_router.py
neutron/tests/unit/test_dvr_router.py [new file with mode: 0644]
neutron/tests/unit/test_l3_agent.py

index 5d5ef5987e342aca004dd89a2dc28420bb5b17d7..dc40135e47eb9511c3f1a8fde707c32492808c82 100644 (file)
@@ -714,7 +714,7 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
             if ri.router['distributed']:
                 # Special Handling for DVR - update FIP namespace
                 # and ri.namespace to handle DVR based FIP
-                self.floating_ip_added_dist(ri, fip, ip_cidr)
+                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.
@@ -735,6 +735,7 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
                                                namespace=ri.ns_name,
                                                ip=ip_cidr)
             if ri.router['distributed']:
+                #TODO(Carl) Call this method on ri.  Needs namespace work.
                 self.floating_ip_removed_dist(ri, ip_cidr)
 
     def _get_router_cidrs(self, ri, device):
index fceb3f5731eb10614496dac635ad16fe3ab39a6d..0e4fa981abfedb337b55b35470fceb2dfd0c9118 100644 (file)
@@ -168,67 +168,12 @@ class AgentMixin(object):
         # kicks the FW Agent to add rules for the snat namespace
         self.process_router_add(ri)
 
-    def floating_ip_added_dist(self, ri, fip, fip_cidr):
-        """Add floating IP to FIP namespace."""
-        floating_ip = fip['floating_ip_address']
-        fixed_ip = fip['fixed_ip_address']
-        rule_pr = ri.fip_ns.allocate_rule_priority()
-        ri.floating_ips_dict[floating_ip] = rule_pr
-        fip_2_rtr_name = ri.fip_ns.get_int_device_name(ri.router_id)
-        ip_rule = ip_lib.IpRule(self.root_helper, namespace=ri.ns_name)
-        ip_rule.add(fixed_ip, dvr_fip_ns.FIP_RT_TBL, rule_pr)
-        #Add routing rule in fip namespace
-        fip_ns_name = ri.fip_ns.get_name()
-        rtr_2_fip, _ = ri.rtr_fip_subnet.get_pair()
-        device = ip_lib.IPDevice(fip_2_rtr_name, self.root_helper,
-                                 namespace=fip_ns_name)
-        device.route.add_route(fip_cidr, str(rtr_2_fip.ip))
-        interface_name = (
-            ri.fip_ns.get_ext_device_name(ri.fip_ns.agent_gateway_port['id']))
-        ip_lib.send_garp_for_proxyarp(fip_ns_name,
-                                      interface_name,
-                                      floating_ip,
-                                      self.conf.send_arp_for_ha,
-                                      self.root_helper)
-        # update internal structures
-        ri.dist_fip_count = ri.dist_fip_count + 1
-
     def floating_ip_removed_dist(self, ri, fip_cidr):
         """Remove floating IP from FIP namespace."""
-        floating_ip = fip_cidr.split('/')[0]
-        rtr_2_fip_name = ri.fip_ns.get_rtr_ext_device_name(ri.router_id)
-        fip_2_rtr_name = ri.fip_ns.get_int_device_name(ri.router_id)
-        if ri.rtr_fip_subnet is None:
-            ri.rtr_fip_subnet = self.local_subnets.allocate(ri.router_id)
-        rtr_2_fip, fip_2_rtr = ri.rtr_fip_subnet.get_pair()
-        fip_ns_name = ri.fip_ns.get_name()
-        if floating_ip in ri.floating_ips_dict:
-            rule_pr = ri.floating_ips_dict[floating_ip]
-            ip_rule = ip_lib.IpRule(self.root_helper, namespace=ri.ns_name)
-            ip_rule.delete(floating_ip, dvr_fip_ns.FIP_RT_TBL, rule_pr)
-            ri.fip_ns.deallocate_rule_priority(rule_pr)
-            #TODO(rajeev): Handle else case - exception/log?
-
-        device = ip_lib.IPDevice(fip_2_rtr_name, self.root_helper,
-                                 namespace=fip_ns_name)
-
-        device.route.delete_route(fip_cidr, str(rtr_2_fip.ip))
-        # check if this is the last FIP for this router
-        ri.dist_fip_count = ri.dist_fip_count - 1
-        if ri.dist_fip_count == 0:
-            #remove default route entry
-            device = ip_lib.IPDevice(rtr_2_fip_name, self.root_helper,
-                                     namespace=ri.ns_name)
-            ns_ip = ip_lib.IPWrapper(self.root_helper, namespace=fip_ns_name)
-            device.route.delete_gateway(str(fip_2_rtr.ip),
-                                        table=dvr_fip_ns.FIP_RT_TBL)
-            ri.fip_ns.local_subnets.release(ri.router_id)
-            ri.rtr_fip_subnet = None
-            ns_ip.del_veth(fip_2_rtr_name)
-            is_last = ri.fip_ns.unsubscribe(ri.router_id)
-            # clean up fip-namespace if this is the last FIP
-            if is_last:
-                self._destroy_fip_namespace(fip_ns_name)
+        is_last = ri.floating_ip_removed_dist(fip_cidr)
+        # clean up fip-namespace if this is the last FIP
+        if is_last:
+            self._destroy_fip_namespace(ri.fip_ns.get_name())
 
     def _snat_redirect_add(self, ri, gateway, sn_port, sn_int):
         """Adds rules and routes for SNAT redirection."""
index 8ad32da9a83956f6366584d673b5c4e4967aeb00..7b44e7df8c1d54fb78617f138cda2341578e1a92 100644 (file)
@@ -12,7 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from neutron.agent.l3 import dvr_fip_ns
 from neutron.agent.l3 import router_info as router
+from neutron.agent.linux import ip_lib
 
 
 class DvrRouter(router.RouterInfo):
@@ -47,3 +49,68 @@ class DvrRouter(router.RouterInfo):
                     {'interface_name': interface_name})
             self.iptables_manager.ipv4['nat'].add_rule(*rule)
         self.iptables_manager.apply()
+
+    def floating_ip_added_dist(self, fip, fip_cidr):
+        """Add floating IP to FIP namespace."""
+        floating_ip = fip['floating_ip_address']
+        fixed_ip = fip['fixed_ip_address']
+        rule_pr = self.fip_ns.allocate_rule_priority()
+        self.floating_ips_dict[floating_ip] = rule_pr
+        fip_2_rtr_name = self.fip_ns.get_int_device_name(self.router_id)
+        ip_rule = ip_lib.IpRule(self.root_helper, namespace=self.ns_name)
+        ip_rule.add(fixed_ip, dvr_fip_ns.FIP_RT_TBL, rule_pr)
+        #Add routing rule in fip namespace
+        fip_ns_name = self.fip_ns.get_name()
+        rtr_2_fip, _ = self.rtr_fip_subnet.get_pair()
+        device = ip_lib.IPDevice(fip_2_rtr_name, self.root_helper,
+                                 namespace=fip_ns_name)
+        device.route.add_route(fip_cidr, str(rtr_2_fip.ip))
+        interface_name = (
+            self.fip_ns.get_ext_device_name(
+                self.fip_ns.agent_gateway_port['id']))
+        ip_lib.send_garp_for_proxyarp(fip_ns_name,
+                                      interface_name,
+                                      floating_ip,
+                                      self.agent_conf.send_arp_for_ha,
+                                      self.root_helper)
+        # update internal structures
+        self.dist_fip_count = self.dist_fip_count + 1
+
+    def floating_ip_removed_dist(self, fip_cidr):
+        """Remove floating IP from FIP namespace."""
+        floating_ip = fip_cidr.split('/')[0]
+        rtr_2_fip_name = self.fip_ns.get_rtr_ext_device_name(self.router_id)
+        fip_2_rtr_name = self.fip_ns.get_int_device_name(self.router_id)
+        if self.rtr_fip_subnet is None:
+            self.rtr_fip_subnet = self.local_subnets.allocate(self.router_id)
+
+        rtr_2_fip, fip_2_rtr = self.rtr_fip_subnet.get_pair()
+        fip_ns_name = self.fip_ns.get_name()
+        if floating_ip in self.floating_ips_dict:
+            rule_pr = self.floating_ips_dict[floating_ip]
+            ip_rule = ip_lib.IpRule(self.root_helper, namespace=self.ns_name)
+            ip_rule.delete(floating_ip, dvr_fip_ns.FIP_RT_TBL, rule_pr)
+            self.fip_ns.deallocate_rule_priority(rule_pr)
+            #TODO(rajeev): Handle else case - exception/log?
+
+        device = ip_lib.IPDevice(fip_2_rtr_name, self.root_helper,
+                                 namespace=fip_ns_name)
+
+        device.route.delete_route(fip_cidr, str(rtr_2_fip.ip))
+        # check if this is the last FIP for this router
+        self.dist_fip_count = self.dist_fip_count - 1
+        is_last = False
+        if self.dist_fip_count == 0:
+            #remove default route entry
+            device = ip_lib.IPDevice(rtr_2_fip_name,
+                                     self.root_helper,
+                                     namespace=self.ns_name)
+            ns_ip = ip_lib.IPWrapper(self.root_helper,
+                                     namespace=fip_ns_name)
+            device.route.delete_gateway(str(fip_2_rtr.ip),
+                                        table=dvr_fip_ns.FIP_RT_TBL)
+            self.fip_ns.local_subnets.release(self.router_id)
+            self.rtr_fip_subnet = None
+            ns_ip.del_veth(fip_2_rtr_name)
+            is_last = self.fip_ns.unsubscribe(self.router_id)
+        return is_last
diff --git a/neutron/tests/unit/test_dvr_router.py b/neutron/tests/unit/test_dvr_router.py
new file mode 100644 (file)
index 0000000..4552d73
--- /dev/null
@@ -0,0 +1,114 @@
+# 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.linux import ip_lib
+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, **kwargs):
+        agent_conf = mock.Mock()
+        return dvr_router.DvrRouter(mock.sentinel.router_id,
+                                    router,
+                                    mock.sentinel.root_helper,
+                                    agent_conf,
+                                    mock.sentinel.interface_driver,
+                                    **kwargs)
+
+    @mock.patch.object(ip_lib, 'send_garp_for_proxyarp')
+    @mock.patch.object(ip_lib, 'IPDevice')
+    @mock.patch.object(ip_lib, 'IpRule')
+    def test_floating_ip_added_dist(self, mIpRule, mIPDevice, mock_arp):
+        router = mock.MagicMock()
+        ri = self._create_router(router)
+        ext_net_id = _uuid()
+        agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30',
+                                        'subnet_id': _uuid()}],
+                         'subnet': {'gateway_ip': '20.0.0.1'},
+                         'id': _uuid(),
+                         'network_id': ext_net_id,
+                         'mac_address': 'ca:fe:de:ad:be:ef',
+                         'ip_cidr': '20.0.0.30/24'}
+
+        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().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)
+
+        agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30',
+                                        'subnet_id': _uuid()}],
+                         'subnet': {'gateway_ip': '20.0.0.1'},
+                         'id': _uuid(),
+                         'network_id': _uuid(),
+                         'mac_address': 'ca:fe:de:ad:be:ef',
+                         'ip_cidr': '20.0.0.30/24'}
+        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().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()
+        ri.floating_ip_removed_dist(fip_cidr)
+        mIPWrapper().del_veth.assert_called_once_with(
+            ri.fip_ns.get_int_device_name(router['id']))
+        mIPDevice().route.delete_gateway.assert_called_once_with(
+            str(fip_to_rtr.ip), table=16)
+        ri.fip_ns.unsubscribe.assert_called_once_with(ri.router_id)
index 7206e4b3b17af54e869436de754ddef13e208fc4..b066a1761b143c0dc1af891d91e2ec872cab46e1 100644 (file)
@@ -38,7 +38,6 @@ from neutron.agent.metadata import driver as metadata_driver
 from neutron.common import config as base_config
 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 _LE
 from neutron.openstack.common import log
 from neutron.openstack.common import uuidutils
@@ -1772,77 +1771,6 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
         self.assertEqual(self.mock_driver.plug.call_count, 3)
         self.assertEqual(self.mock_driver.init_l3.call_count, 3)
 
-    def test_floating_ip_added_dist(self):
-        agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
-        router = prepare_router_data()
-        ri = dvr_router.DvrRouter(router['id'], router, **self.ri_kwargs)
-        ext_net_id = _uuid()
-        agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30',
-                                        'subnet_id': _uuid()}],
-                         'subnet': {'gateway_ip': '20.0.0.1'},
-                         'id': _uuid(),
-                         'network_id': ext_net_id,
-                         'mac_address': 'ca:fe:de:ad:be:ef',
-                         'ip_cidr': '20.0.0.30/24'}
-
-        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 = agent.get_fip_ns(ext_net_id)
-        ri.fip_ns.agent_gateway_port = agent_gw_port
-        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'])
-        agent.floating_ip_added_dist(ri, fip, ip_cidr)
-        self.mock_rule.add.assert_called_with('192.168.0.1', 16, FIP_PRI)
-        # TODO(mrsmith): add more asserts
-
-    @mock.patch.object(lla.LinkLocalAllocator, '_write')
-    def test_floating_ip_removed_dist(self, write):
-        agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
-        router = prepare_router_data()
-        agent_gw_port = {'fixed_ips': [{'ip_address': '20.0.0.30',
-                                        'subnet_id': _uuid()}],
-                         'subnet': {'gateway_ip': '20.0.0.1'},
-                         'id': _uuid(),
-                         'network_id': _uuid(),
-                         'mac_address': 'ca:fe:de:ad:be:ef',
-                         'ip_cidr': '20.0.0.30/24'}
-        fip_cidr = '11.22.33.44/24'
-
-        ri = dvr_router.DvrRouter(router['id'], router, **self.ri_kwargs)
-        ri.dist_fip_count = 2
-        ri.fip_ns = agent.get_fip_ns(agent._fetch_external_net_id())
-        ri.fip_ns.unsubscribe = mock.Mock()
-        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'
-        agent.agent_gateway_port = agent_gw_port
-        s = lla.LinkLocalAddressPair('169.254.30.42/31')
-        ri.rtr_fip_subnet = s
-        agent.floating_ip_removed_dist(ri, fip_cidr)
-        floating_ip = fip_cidr.split('/')[0]
-        self.mock_rule.delete.assert_called_with(floating_ip, 16, FIP_PRI)
-        self.mock_ip_dev.route.delete_route.assert_called_with(fip_cidr,
-                                                               str(s.ip))
-        self.assertFalse(ri.fip_ns.unsubscribe.called)
-
-        with mock.patch.object(agent, '_destroy_fip_namespace') as f:
-            ri.dist_fip_count = 1
-            fip_ns_name = ri.fip_ns.get_name()
-            ri.rtr_fip_subnet = ri.fip_ns.local_subnets.allocate(ri.router_id)
-            _, fip_to_rtr = ri.rtr_fip_subnet.get_pair()
-            agent.floating_ip_removed_dist(ri, fip_cidr)
-            self.mock_ip.del_veth.assert_called_once_with(
-                ri.fip_ns.get_int_device_name(router['id']))
-            self.mock_ip_dev.route.delete_gateway.assert_called_once_with(
-                str(fip_to_rtr.ip), table=16)
-            f.assert_called_once_with(fip_ns_name)
-        ri.fip_ns.unsubscribe.assert_called_once_with(ri.router_id)
-
     def test_get_service_plugin_list(self):
         service_plugins = [p_const.L3_ROUTER_NAT]
         self.plugin_api.get_service_plugin_list.return_value = service_plugins