From cd33dbee09ca8335bcb5ba6975a8edd16258babe Mon Sep 17 00:00:00 2001 From: Joe Mills Date: Mon, 11 Nov 2013 06:49:17 +0000 Subject: [PATCH] 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 --- neutron/plugins/midonet/plugin.py | 61 +++++++++++-------- .../tests/unit/midonet/test_midonet_plugin.py | 45 ++++++++++++++ 2 files changed, 80 insertions(+), 26 deletions(-) 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): -- 2.45.2