Fix floating IP management from instance panel.

Quantum Floating IP API works with ports ids not instances ones
(opposite to what Nova Network does). So if we want to associate
(disassociate) an allocated floating IP to some instance we must
use the "target_id" (which is a port_id in case of Quantum and an
instance_id in case of Nova network).

Fixes bug 1158596.

Change-Id: Iceba4d8ee74bd58dc1cdbda7668841b0a7eb86f1
This commit is contained in:
Roman Podolyaka 2013-04-09 16:28:40 +03:00
parent 527c0a1d86
commit de1940c922
2 changed files with 72 additions and 4 deletions

View File

@ -326,10 +326,15 @@ class SimpleAssociateIP(tables.Action):
return False
return not is_deleting(instance)
def single(self, table, request, instance):
def single(self, table, request, instance_id):
try:
# target_id is port_id for Quantum and instance_id for Nova Network
# (Quantum API wrapper returns a 'portid_fixedip' string)
target_id = api.network.floating_ip_target_get_by_instance(
request, instance_id).split('_')[0]
fip = api.network.tenant_floating_ip_allocate(request)
api.network.floating_ip_associate(request, fip.id, instance)
api.network.floating_ip_associate(request, fip.id, target_id)
messages.success(request,
_("Successfully associated floating IP: %s")
% fip.ip)
@ -351,14 +356,19 @@ class SimpleDisassociateIP(tables.Action):
def single(self, table, request, instance_id):
try:
# target_id is port_id for Quantum and instance_id for Nova Network
# (Quantum API wrapper returns a 'portid_fixedip' string)
target_id = api.network.floating_ip_target_get_by_instance(
request, instance_id).split('_')[0]
fips = [fip for fip in api.network.tenant_floating_ip_list(request)
if fip.port_id == instance_id]
if fip.port_id == target_id]
# Removing multiple floating IPs at once doesn't work, so this pops
# off the first one.
if fips:
fip = fips.pop()
api.network.floating_ip_disassociate(request,
fip.id, instance_id)
fip.id, target_id)
api.network.tenant_floating_ip_release(request, fip.id)
messages.success(request,
_("Successfully disassociated "

View File

@ -1271,3 +1271,61 @@ class InstanceTests(test.TestCase):
"%(key)s</option>" % {'key': keypair.name},
html=True,
msg_prefix="The default keypair was not selected.")
@test.create_stubs({api.network: ('floating_ip_target_get_by_instance',
'tenant_floating_ip_allocate',
'floating_ip_associate'),
api.nova: ('server_list',
'flavor_list')})
def test_associate_floating_ip(self):
server = self.servers.first()
fip = self.q_floating_ips.first()
api.nova.server_list(
IsA(http.HttpRequest)).AndReturn(self.servers.list())
api.nova.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
api.network.floating_ip_target_get_by_instance(
IsA(http.HttpRequest),
server.id).AndReturn(server.id)
api.network.tenant_floating_ip_allocate(
IsA(http.HttpRequest)).AndReturn(fip)
api.network.floating_ip_associate(
IsA(http.HttpRequest), fip.id, server.id)
self.mox.ReplayAll()
formData = {'action': 'instances__associate-simple__%s' % server.id}
res = self.client.post(INDEX_URL, formData)
self.assertRedirectsNoFollow(res, INDEX_URL)
@test.create_stubs({api.network: ('floating_ip_target_get_by_instance',
'tenant_floating_ip_list',
'floating_ip_disassociate',
'tenant_floating_ip_release'),
api.nova: ('server_list',
'flavor_list')})
def test_disassociate_floating_ip(self):
server = self.servers.first()
fip = self.q_floating_ips.first()
fip.port_id = server.id
api.nova.server_list(
IsA(http.HttpRequest)).AndReturn(self.servers.list())
api.nova.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
api.network.floating_ip_target_get_by_instance(
IsA(http.HttpRequest),
server.id).AndReturn(server.id)
api.network.tenant_floating_ip_list(
IsA(http.HttpRequest)).AndReturn([fip])
api.network.floating_ip_disassociate(
IsA(http.HttpRequest), fip.id, server.id)
api.network.tenant_floating_ip_release(
IsA(http.HttpRequest), fip.id)
self.mox.ReplayAll()
formData = {'action': 'instances__disassociate__%s' % server.id}
res = self.client.post(INDEX_URL, formData)
self.assertRedirectsNoFollow(res, INDEX_URL)