From 155e3ae7c3e6e51937c801c10dd976e589af8969 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Thu, 15 Nov 2012 21:35:55 +0400 Subject: [PATCH] Fix handling of UUID-typed flavor ids Change the type of flavor_id hidden field in EditFlavor form from IntegerField to CharField since flavor id is a string representation of UUID now. Additionally change the type of similar hidden fields in CreateExtraSpec and EditExtraSpec forms. Remove flavor id generation from form handling code. Id generation should be done only in corresponding OpenStack components (nova, etc.). Since nova supports flavor id autogeneration and 'flavorid' parameter of FlavorManager.create() in novaclient is optional, remove 'flavorid' parameter from api.nova.flavor_create(). Change flavor ids in test data from strings containing integers to UUID-like strings to make them correspond to real data. Update flavor tests to make them compatible with new api.nova.flavor_create() signature. Remove conversions of flavor id to int from all tests. In particular, update test_index_flavor_get_exception() to make it generate unique UUID flavor ids instead of integers. Fixes bug #1076761 Change-Id: Iaa308578981f0379ff61a9dd42620eaf0ab1d605 --- openstack_dashboard/api/nova.py | 7 +++---- .../dashboards/admin/flavors/extras/forms.py | 4 ++-- .../dashboards/admin/flavors/extras/tests.py | 2 +- openstack_dashboard/dashboards/admin/flavors/forms.py | 8 ++------ openstack_dashboard/dashboards/admin/flavors/tests.py | 6 ++---- .../dashboards/admin/instances/tests.py | 10 ++++++---- .../dashboards/project/instances/tests.py | 10 ++++++---- openstack_dashboard/test/test_data/nova_data.py | 4 ++-- run_tests.sh | 2 +- tools/pip-requires | 2 +- 10 files changed, 26 insertions(+), 29 deletions(-) diff --git a/openstack_dashboard/api/nova.py b/openstack_dashboard/api/nova.py index 822645753..c89c1edb2 100644 --- a/openstack_dashboard/api/nova.py +++ b/openstack_dashboard/api/nova.py @@ -195,10 +195,9 @@ def server_vnc_console(request, instance_id, console_type='novnc'): console_type)['console']) -def flavor_create(request, name, memory, vcpu, disk, flavor_id, ephemeral=0): - return novaclient(request).flavors.create(name, int(memory), int(vcpu), - int(disk), flavor_id, - ephemeral=int(ephemeral)) +def flavor_create(request, name, memory, vcpu, disk, ephemeral=0): + return novaclient(request).flavors.create(name, memory, vcpu, + disk, ephemeral=ephemeral) def flavor_delete(request, flavor_id): diff --git a/openstack_dashboard/dashboards/admin/flavors/extras/forms.py b/openstack_dashboard/dashboards/admin/flavors/extras/forms.py index 5cada8ec4..93d37ee94 100644 --- a/openstack_dashboard/dashboards/admin/flavors/extras/forms.py +++ b/openstack_dashboard/dashboards/admin/flavors/extras/forms.py @@ -33,7 +33,7 @@ LOG = logging.getLogger(__name__) class CreateExtraSpec(forms.SelfHandlingForm): key = forms.CharField(max_length="25", label=_("Key")) value = forms.CharField(max_length="25", label=_("Value")) - flavor_id = forms.IntegerField(widget=forms.widgets.HiddenInput) + flavor_id = forms.CharField(widget=forms.widgets.HiddenInput) def handle(self, request, data): try: @@ -51,7 +51,7 @@ class CreateExtraSpec(forms.SelfHandlingForm): class EditExtraSpec(forms.SelfHandlingForm): key = forms.CharField(max_length="25", label=_("Key")) value = forms.CharField(max_length="25", label=_("Value")) - flavor_id = forms.IntegerField(widget=forms.widgets.HiddenInput) + flavor_id = forms.CharField(widget=forms.widgets.HiddenInput) def handle(self, request, data): flavor_id = data['flavor_id'] diff --git a/openstack_dashboard/dashboards/admin/flavors/extras/tests.py b/openstack_dashboard/dashboards/admin/flavors/extras/tests.py index a8df96896..f570aec23 100644 --- a/openstack_dashboard/dashboards/admin/flavors/extras/tests.py +++ b/openstack_dashboard/dashboards/admin/flavors/extras/tests.py @@ -37,7 +37,7 @@ class FlavorExtrasTests(test.BaseAdminViewTests): # GET to display the flavor_name api.nova.flavor_extra_set(IsA(http.HttpRequest), - int(flavor.id), + flavor.id, {'k1': 'v1'}) self.mox.ReplayAll() diff --git a/openstack_dashboard/dashboards/admin/flavors/forms.py b/openstack_dashboard/dashboards/admin/flavors/forms.py index b66217e33..c98604b5f 100644 --- a/openstack_dashboard/dashboards/admin/flavors/forms.py +++ b/openstack_dashboard/dashboards/admin/flavors/forms.py @@ -19,7 +19,6 @@ # under the License. import logging -import uuid from django.utils.translation import ugettext_lazy as _ @@ -65,7 +64,6 @@ class CreateFlavor(forms.SelfHandlingForm): data['memory_mb'], data['vcpus'], data['disk_gb'], - uuid.uuid4(), ephemeral=data['eph_gb']) msg = _('Created flavor "%s".') % data['name'] messages.success(request, msg) @@ -75,7 +73,7 @@ class CreateFlavor(forms.SelfHandlingForm): class EditFlavor(CreateFlavor): - flavor_id = forms.IntegerField(widget=forms.widgets.HiddenInput) + flavor_id = forms.CharField(widget=forms.widgets.HiddenInput) def clean_name(self): return self.cleaned_data['name'] @@ -92,16 +90,14 @@ class EditFlavor(CreateFlavor): # This is in the same try/except block as the delete call # because if the delete fails the API will error out because # active flavors can't have the same name. - new_flavor_id = uuid.uuid4() flavor = api.nova.flavor_create(request, data['name'], data['memory_mb'], data['vcpus'], data['disk_gb'], - new_flavor_id, ephemeral=data['eph_gb']) if (len(extras_dict) > 0): - api.nova.flavor_extra_set(request, new_flavor_id, extras_dict) + api.nova.flavor_extra_set(request, flavor.id, extras_dict) msg = _('Updated flavor "%s".') % data['name'] messages.success(request, msg) return flavor diff --git a/openstack_dashboard/dashboards/admin/flavors/tests.py b/openstack_dashboard/dashboards/admin/flavors/tests.py index 06c265093..1dfa49a1a 100644 --- a/openstack_dashboard/dashboards/admin/flavors/tests.py +++ b/openstack_dashboard/dashboards/admin/flavors/tests.py @@ -21,7 +21,6 @@ class FlavorsTests(test.BaseAdminViewTests): flavor.ram, flavor.vcpus, flavor.disk, - IsA(uuid.uuid4()), ephemeral=eph).AndReturn(flavor) api.nova.flavor_list(IsA(http.HttpRequest)) self.mox.ReplayAll() @@ -55,15 +54,14 @@ class FlavorsTests(test.BaseAdminViewTests): # POST api.nova.flavor_get(IsA(http.HttpRequest), flavor.id).AndReturn(flavor) - api.nova.flavor_get_extras(IsA(http.HttpRequest), int(flavor.id))\ + api.nova.flavor_get_extras(IsA(http.HttpRequest), flavor.id)\ .AndReturn(extras) - api.nova.flavor_delete(IsA(http.HttpRequest), int(flavor.id)) + api.nova.flavor_delete(IsA(http.HttpRequest), flavor.id) api.nova.flavor_create(IsA(http.HttpRequest), flavor.name, flavor.ram, flavor.vcpus + 1, flavor.disk, - IsA(uuid.uuid4()), ephemeral=eph).AndReturn(flavor) self.mox.ReplayAll() diff --git a/openstack_dashboard/dashboards/admin/instances/tests.py b/openstack_dashboard/dashboards/admin/instances/tests.py index 475673689..c29e828a9 100644 --- a/openstack_dashboard/dashboards/admin/instances/tests.py +++ b/openstack_dashboard/dashboards/admin/instances/tests.py @@ -14,6 +14,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 from django.utils.datastructures import SortedDict @@ -76,10 +78,10 @@ class InstanceViewTest(test.BaseAdminViewTests): servers = self.servers.list() flavors = self.flavors.list() tenants = self.tenants.list() - max_id = max([int(flavor.id) for flavor in flavors]) - for server in servers: - max_id += 1 - server.flavor["id"] = max_id + # UUIDs generated using indexes are unlikely to match + # any of existing flavor ids and are guaranteed to be deterministic. + for i, server in enumerate(servers): + server.flavor['id'] = str(uuid.UUID(int=i)) api.nova.server_list(IsA(http.HttpRequest), all_tenants=True).AndReturn(servers) diff --git a/openstack_dashboard/dashboards/project/instances/tests.py b/openstack_dashboard/dashboards/project/instances/tests.py index d7321ce61..21bb80d83 100644 --- a/openstack_dashboard/dashboards/project/instances/tests.py +++ b/openstack_dashboard/dashboards/project/instances/tests.py @@ -18,6 +18,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 from django.utils.http import urlencode @@ -90,10 +92,10 @@ class InstanceTests(test.TestCase): def test_index_flavor_get_exception(self): servers = self.servers.list() flavors = self.flavors.list() - max_id = max([int(flavor.id) for flavor in flavors]) - for server in servers: - max_id += 1 - server.flavor["id"] = max_id + # UUIDs generated using indexes are unlikely to match + # any of existing flavor ids and are guaranteed to be deterministic. + for i, server in enumerate(servers): + server.flavor['id'] = str(uuid.UUID(int=i)) api.server_list(IsA(http.HttpRequest)).AndReturn(servers) api.flavor_list(IsA(http.HttpRequest)).AndReturn(flavors) diff --git a/openstack_dashboard/test/test_data/nova_data.py b/openstack_dashboard/test/test_data/nova_data.py index 26ec973e8..0bd7c3a8e 100644 --- a/openstack_dashboard/test/test_data/nova_data.py +++ b/openstack_dashboard/test/test_data/nova_data.py @@ -198,14 +198,14 @@ def data(TEST): # Flavors flavor_1 = flavors.Flavor(flavors.FlavorManager(None), - {'id': "1", + {'id': "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", 'name': 'm1.tiny', 'vcpus': 1, 'disk': 0, 'ram': 512, 'OS-FLV-EXT-DATA:ephemeral': 0}) flavor_2 = flavors.Flavor(flavors.FlavorManager(None), - {'id': "2", + {'id': "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", 'name': 'm1.massive', 'vcpus': 1000, 'disk': 1024, diff --git a/run_tests.sh b/run_tests.sh index 708953649..d3357c146 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -6,7 +6,7 @@ set -o errexit # Increment me any time the environment should be rebuilt. # This includes dependncy changes, directory renames, etc. # Simple integer secuence: 1, 2, 3... -environment_version=28 +environment_version=29 #--------------------------------------------------------# function usage { diff --git a/tools/pip-requires b/tools/pip-requires index bd4678696..b10fdf9a8 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -6,7 +6,7 @@ netaddr python-cinderclient python-glanceclient<2 python-keystoneclient -python-novaclient +python-novaclient>=2.10.0,<3 python-quantumclient>=2.0 python-swiftclient>1.1,<2 pytz