]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Midonet to support port association at floating IP creation
authorJoe Mills <joe@midokura.com>
Mon, 11 Nov 2013 06:49:17 +0000 (06:49 +0000)
committerJoe Mills <joe@midokura.com>
Wed, 13 Nov 2013 05:09:04 +0000 (05:09 +0000)
The Midonet plugin currently does not support associating floating IPs with
ports at floating IP creation time. This bug is created to add this support.

Change-Id: Ie57ebffa5185f26138c04b9836067417c6dc1388
Closes-Bug: #1249957

neutron/plugins/midonet/plugin.py
neutron/tests/unit/midonet/test_midonet_plugin.py

index ca2cb9c186769ab432c62ca00381ac7651f36854..1884baad78fd6f242861617a447df101cdc79df2 100644 (file)
@@ -1026,6 +1026,40 @@ class MidonetPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
                     "info=%r"), info)
         return info
 
+    def _assoc_fip(self, fip):
+        router = self.client.get_router(fip["router_id"])
+        link_port = self.client.get_link_port(
+            self._get_provider_router(), router.get_id())
+        self.client.add_router_route(
+            self._get_provider_router(),
+            src_network_addr='0.0.0.0',
+            src_network_length=0,
+            dst_network_addr=fip["floating_ip_address"],
+            dst_network_length=32,
+            next_hop_port=link_port.get_peer_id())
+        props = {OS_FLOATING_IP_RULE_KEY: fip['id']}
+        tenant_id = router.get_tenant_id()
+        chain_names = _nat_chain_names(router.get_id())
+        for chain_type, name in chain_names.items():
+            src_ip, target_ip = _get_nat_ips(chain_type, fip)
+            if chain_type == 'pre-routing':
+                nat_type = 'dnat'
+            else:
+                nat_type = 'snat'
+            self.client.add_static_nat(tenant_id, name, src_ip,
+                                       target_ip,
+                                       link_port.get_id(),
+                                       nat_type, **props)
+
+    def create_floatingip(self, context, floatingip):
+        session = context.session
+        with session.begin(subtransactions=True):
+            fip = super(MidonetPluginV2, self).create_floatingip(
+                context, floatingip)
+            if fip['port_id']:
+                self._assoc_fip(fip)
+        return fip
+
     def update_floatingip(self, context, id, floatingip):
         """Handle floating IP assocation and disassociation."""
         LOG.debug(_("MidonetPluginV2.update_floatingip called: id=%(id)s "
@@ -1038,32 +1072,7 @@ class MidonetPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
                 fip = super(MidonetPluginV2, self).update_floatingip(
                     context, id, floatingip)
 
-                # Add a route for the floating IP on the provider router.
-                router = self.client.get_router(fip["router_id"])
-                link_port = self.client.get_link_port(
-                    self._get_provider_router(), router.get_id())
-                self.client.add_router_route(
-                    self._get_provider_router(),
-                    src_network_addr='0.0.0.0',
-                    src_network_length=0,
-                    dst_network_addr=fip["floating_ip_address"],
-                    dst_network_length=32,
-                    next_hop_port=link_port.get_peer_id())
-
-                # Add static SNAT and DNAT rules on the tenant router.
-                props = {OS_FLOATING_IP_RULE_KEY: id}
-                tenant_id = router.get_tenant_id()
-                chain_names = _nat_chain_names(router.get_id())
-                for chain_type, name in chain_names.iteritems():
-                    src_ip, target_ip = _get_nat_ips(chain_type, fip)
-                    if chain_type == 'pre-routing':
-                        nat_type = 'dnat'
-                    else:
-                        nat_type = 'snat'
-                    self.client.add_static_nat(tenant_id, name, src_ip,
-                                               target_ip,
-                                               link_port.get_id(),
-                                               nat_type, **props)
+                self._assoc_fip(fip)
 
             # disassociate floating IP
             elif floatingip['floatingip']['port_id'] is None:
index e432db861465aa8c595b459fffc4222cd5c6a5a0..fcff772873ef81de2dec2f2783dc55c42b246f97 100644 (file)
@@ -81,6 +81,51 @@ class TestMidonetL3NatTestCase(test_l3_plugin.L3NatDBIntTestCase,
     def test_floatingip_with_invalid_create_port(self):
         self._test_floatingip_with_invalid_create_port(MIDONET_PLUGIN_NAME)
 
+    def test_floatingip_assoc_no_port(self):
+        with self.subnet(cidr='200.0.0.0/24') as public_sub:
+            self._set_net_external(public_sub['subnet']['network_id'])
+            res = super(TestMidonetL3NatTestCase, self)._create_floatingip(
+                self.fmt, public_sub['subnet']['network_id'])
+            # Cleanup
+            floatingip = self.deserialize(self.fmt, res)
+            self._delete('floatingips', floatingip['floatingip']['id'])
+        self.assertFalse(self.instance.return_value.add_static_nat.called)
+
+    def test_floatingip_assoc_with_port(self):
+        with self.subnet(cidr='200.0.0.0/24') as public_sub:
+            self._set_net_external(public_sub['subnet']['network_id'])
+            with self.port() as private_port:
+                with self.router() as r:
+                    # We need to hook up the private subnet to the external
+                    # network in order to associate the fip.
+                    sid = private_port['port']['fixed_ips'][0]['subnet_id']
+                    private_sub = {'subnet': {'id': sid}}
+                    self._add_external_gateway_to_router(
+                        r['router']['id'],
+                        public_sub['subnet']['network_id'])
+                    self._router_interface_action('add', r['router']['id'],
+                                                  private_sub['subnet']['id'],
+                                                  None)
+
+                    # Create the fip.
+                    res = super(TestMidonetL3NatTestCase,
+                                self)._create_floatingip(
+                                    self.fmt,
+                                    public_sub['subnet']['network_id'],
+                                    port_id=private_port['port']['id'])
+
+                    # Cleanup the resources used for the test
+                    floatingip = self.deserialize(self.fmt, res)
+                    self._delete('floatingips', floatingip['floatingip']['id'])
+                    self._remove_external_gateway_from_router(
+                        r['router']['id'],
+                        public_sub['subnet']['network_id'])
+                    self._router_interface_action('remove',
+                                                  r['router']['id'],
+                                                  private_sub['subnet']['id'],
+                                                  None)
+        self.assertTrue(self.instance.return_value.add_static_nat.called)
+
 
 class TestMidonetSecurityGroupsTestCase(sg.SecurityGroupDBTestCase):