diff --git a/neutron/plugins/midonet/plugin.py b/neutron/plugins/midonet/plugin.py index 8016ef56ab..e4bdb99559 100644 --- a/neutron/plugins/midonet/plugin.py +++ b/neutron/plugins/midonet/plugin.py @@ -1044,6 +1044,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 association and disassociation.""" LOG.debug(_("MidonetPluginV2.update_floatingip called: id=%(id)s " @@ -1056,32 +1090,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: diff --git a/neutron/tests/unit/midonet/test_midonet_plugin.py b/neutron/tests/unit/midonet/test_midonet_plugin.py index 5ecab720da..1822f9364a 100644 --- a/neutron/tests/unit/midonet/test_midonet_plugin.py +++ b/neutron/tests/unit/midonet/test_midonet_plugin.py @@ -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):