Skip to content

Commit

Permalink
Midonet to support port association at floating IP creation
Browse files Browse the repository at this point in the history
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
  • Loading branch information
JoeMido committed Nov 13, 2013
1 parent 0e2198e commit cd33dbe
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 26 deletions.
61 changes: 35 additions & 26 deletions neutron/plugins/midonet/plugin.py
Expand Up @@ -1026,6 +1026,40 @@ def add_router_interface(self, context, router_id, interface_info):
"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 "
Expand All @@ -1038,32 +1072,7 @@ def update_floatingip(self, context, id, floatingip):
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:
Expand Down
45 changes: 45 additions & 0 deletions neutron/tests/unit/midonet/test_midonet_plugin.py
Expand Up @@ -81,6 +81,51 @@ def setUp(self,
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):

Expand Down

0 comments on commit cd33dbe

Please sign in to comment.