From: Joe Mills Date: Mon, 11 Nov 2013 06:49:17 +0000 (+0000) Subject: Midonet to support port association at floating IP creation X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=cd33dbee09ca8335bcb5ba6975a8edd16258babe;p=openstack-build%2Fneutron-build.git Midonet to support port association at floating IP creation 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 --- diff --git a/neutron/plugins/midonet/plugin.py b/neutron/plugins/midonet/plugin.py index ca2cb9c18..1884baad7 100644 --- a/neutron/plugins/midonet/plugin.py +++ b/neutron/plugins/midonet/plugin.py @@ -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: diff --git a/neutron/tests/unit/midonet/test_midonet_plugin.py b/neutron/tests/unit/midonet/test_midonet_plugin.py index e432db861..fcff77287 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):