Accepts UUID as an ID of Floating IP

Fixes bug 1052561.

In Quanutm, Floating IPs are identified by UUID instead of integer ID.
After quantum-nova integration for FLoating IP has been implemented,
Horizon also needs to accept UUID style of ID for Floating IP.

Change-Id: I6ed919cbbc818c97cecef2fe3a91c8e5a7ac76e0
This commit is contained in:
Akihiro MOTOKI 2012-11-13 21:45:03 +09:00
parent 8734ea4977
commit 7ab5ace768
6 changed files with 94 additions and 7 deletions

View File

@ -28,6 +28,8 @@ from horizon import tables
from openstack_dashboard import api
from .utils import get_int_or_uuid
LOG = logging.getLogger(__name__)
@ -83,7 +85,7 @@ class DisassociateIP(tables.Action):
def single(self, table, request, obj_id):
try:
fip = table.get_object_by_id(int(obj_id))
fip = table.get_object_by_id(get_int_or_uuid(obj_id))
api.server_remove_floating_ip(request, fip.instance_id, fip.id)
LOG.info('Disassociating Floating IP "%s".' % obj_id)
messages.success(request,
@ -118,7 +120,7 @@ class FloatingIPsTable(tables.DataTable):
empty_value="-")
def sanitize_id(self, obj_id):
return int(obj_id)
return get_int_or_uuid(obj_id)
def get_object_display(self, datum):
return datum.ip

View File

@ -19,6 +19,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import uuid
from django import http
from django.core.urlresolvers import reverse
@ -27,6 +29,8 @@ from mox import IsA
from openstack_dashboard import api
from openstack_dashboard.test import helpers as test
from .utils import get_int_or_uuid
INDEX_URL = reverse('horizon:project:access_and_security:index')
NAMESPACE = "horizon:project:access_and_security:floating_ips"
@ -49,10 +53,10 @@ class FloatingIpViewTests(test.TestCase):
workflow = res.context['workflow']
choices = dict(workflow.steps[0].action.fields['ip_id'].choices)
# Verify that our "associated" floating IP isn't in the choices list.
self.assertTrue(self.floating_ips.get(id=1) not in choices)
self.assertTrue(self.floating_ips.first() not in choices)
def test_associate_post(self):
floating_ip = self.floating_ips.get(id=2)
floating_ip = self.floating_ips.list()[1]
server = self.servers.first()
self.mox.StubOutWithMock(api.nova, 'server_add_floating_ip')
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
@ -74,7 +78,7 @@ class FloatingIpViewTests(test.TestCase):
self.assertRedirectsNoFollow(res, INDEX_URL)
def test_associate_post_with_redirect(self):
floating_ip = self.floating_ips.get(id=2)
floating_ip = self.floating_ips.list()[1]
server = self.servers.first()
self.mox.StubOutWithMock(api.nova, 'server_add_floating_ip')
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
@ -97,7 +101,7 @@ class FloatingIpViewTests(test.TestCase):
self.assertRedirectsNoFollow(res, next)
def test_associate_post_with_exception(self):
floating_ip = self.floating_ips.get(id=2)
floating_ip = self.floating_ips.list()[1]
server = self.servers.first()
self.mox.StubOutWithMock(api.nova, 'server_add_floating_ip')
self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
@ -175,3 +179,30 @@ class FloatingIpViewTests(test.TestCase):
action = "floating_ips__disassociate__%s" % floating_ip.id
res = self.client.post(INDEX_URL, {"action": action})
self.assertRedirectsNoFollow(res, INDEX_URL)
class FloatingIpQuantumViewTests(FloatingIpViewTests):
def setUp(self):
super(FloatingIpViewTests, self).setUp()
self.floating_ips = self.floating_ips_uuid
class FloatingIpUtilsTests(test.TestCase):
def test_accept_valid_integer(self):
val = 100
ret = get_int_or_uuid(val)
self.assertEqual(val, ret)
def test_accept_valid_integer_string(self):
val = '100'
ret = get_int_or_uuid(val)
self.assertEqual(int(val), ret)
def test_accept_valid_uuid(self):
val = str(uuid.uuid4())
ret = get_int_or_uuid(val)
self.assertEqual(val, ret)
def test_reject_random_string(self):
val = '55WbJTpJDf'
self.assertRaises(ValueError, get_int_or_uuid, val)

View File

@ -0,0 +1,31 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 NEC Corporation All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import uuid
def get_int_or_uuid(value):
"""Check if a value is valid as UUID or an integer.
This method is mainly used to convert floating IP id to the
appropriate type. For floating IP id, integer is used in Nova's
original implementation, but UUID is used in Quantum based one.
"""
try:
uuid.UUID(value)
return value
except (ValueError, AttributeError):
return int(value)

View File

@ -24,13 +24,15 @@ from horizon import forms
from openstack_dashboard import api
from .utils import get_int_or_uuid
ALLOCATE_URL = "horizon:project:access_and_security:floating_ips:allocate"
class AssociateIPAction(workflows.Action):
ip_id = forms.DynamicTypedChoiceField(label=_("IP Address"),
coerce=int,
coerce=get_int_or_uuid,
empty_value=None,
add_item_link=ALLOCATE_URL)
instance_id = forms.ChoiceField(label=_("Instance"))

View File

@ -86,3 +86,9 @@ class AccessAndSecurityTests(test.TestCase):
self.assertContains(res,
'<option value="101">server_1 (101)</option>')
self.assertContains(res, '<option value="2">server_2 (2)</option>')
class AccessAndSecurityQuantumTests(AccessAndSecurityTests):
def setUp(self):
super(AccessAndSecurityTests, self).setUp()
self.floating_ips = self.floating_ips_uuid

View File

@ -13,6 +13,7 @@
# under the License.
import json
import uuid
from novaclient.v1_1 import (flavors, keypairs, servers, volumes,
volume_types, quotas,
@ -143,6 +144,7 @@ def data(TEST):
TEST.quotas = TestDataContainer()
TEST.quota_usages = TestDataContainer()
TEST.floating_ips = TestDataContainer()
TEST.floating_ips_uuid = TestDataContainer()
TEST.usages = TestDataContainer()
TEST.certs = TestDataContainer()
TEST.volume_snapshots = TestDataContainer()
@ -335,6 +337,19 @@ def data(TEST):
'ip': '58.58.58.58'})
TEST.floating_ips.add(fip_1, fip_2)
# Floating IP with UUID id (for Floating IP with Quantum)
fip_3 = floating_ips.FloatingIP(floating_ips.FloatingIPManager(None),
{'id': str(uuid.uuid4()),
'fixed_ip': '10.0.0.4',
'instance_id': server_1.id,
'ip': '58.58.58.58'})
fip_4 = floating_ips.FloatingIP(floating_ips.FloatingIPManager(None),
{'id': str(uuid.uuid4()),
'fixed_ip': None,
'instance_id': None,
'ip': '58.58.58.58'})
TEST.floating_ips_uuid.add(fip_3, fip_4)
# Usage
usage_vals = {"tenant_id": TEST.tenant.id,
"instance_name": server_1.name,