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
This commit is contained in:
Alexey Izbyshev 2012-11-15 21:35:55 +04:00
parent 8243f755a3
commit 155e3ae7c3
10 changed files with 26 additions and 29 deletions

View File

@ -195,10 +195,9 @@ def server_vnc_console(request, instance_id, console_type='novnc'):
console_type)['console']) console_type)['console'])
def flavor_create(request, name, memory, vcpu, disk, flavor_id, ephemeral=0): def flavor_create(request, name, memory, vcpu, disk, ephemeral=0):
return novaclient(request).flavors.create(name, int(memory), int(vcpu), return novaclient(request).flavors.create(name, memory, vcpu,
int(disk), flavor_id, disk, ephemeral=ephemeral)
ephemeral=int(ephemeral))
def flavor_delete(request, flavor_id): def flavor_delete(request, flavor_id):

View File

@ -33,7 +33,7 @@ LOG = logging.getLogger(__name__)
class CreateExtraSpec(forms.SelfHandlingForm): class CreateExtraSpec(forms.SelfHandlingForm):
key = forms.CharField(max_length="25", label=_("Key")) key = forms.CharField(max_length="25", label=_("Key"))
value = forms.CharField(max_length="25", label=_("Value")) 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): def handle(self, request, data):
try: try:
@ -51,7 +51,7 @@ class CreateExtraSpec(forms.SelfHandlingForm):
class EditExtraSpec(forms.SelfHandlingForm): class EditExtraSpec(forms.SelfHandlingForm):
key = forms.CharField(max_length="25", label=_("Key")) key = forms.CharField(max_length="25", label=_("Key"))
value = forms.CharField(max_length="25", label=_("Value")) 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): def handle(self, request, data):
flavor_id = data['flavor_id'] flavor_id = data['flavor_id']

View File

@ -37,7 +37,7 @@ class FlavorExtrasTests(test.BaseAdminViewTests):
# GET to display the flavor_name # GET to display the flavor_name
api.nova.flavor_extra_set(IsA(http.HttpRequest), api.nova.flavor_extra_set(IsA(http.HttpRequest),
int(flavor.id), flavor.id,
{'k1': 'v1'}) {'k1': 'v1'})
self.mox.ReplayAll() self.mox.ReplayAll()

View File

@ -19,7 +19,6 @@
# under the License. # under the License.
import logging import logging
import uuid
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -65,7 +64,6 @@ class CreateFlavor(forms.SelfHandlingForm):
data['memory_mb'], data['memory_mb'],
data['vcpus'], data['vcpus'],
data['disk_gb'], data['disk_gb'],
uuid.uuid4(),
ephemeral=data['eph_gb']) ephemeral=data['eph_gb'])
msg = _('Created flavor "%s".') % data['name'] msg = _('Created flavor "%s".') % data['name']
messages.success(request, msg) messages.success(request, msg)
@ -75,7 +73,7 @@ class CreateFlavor(forms.SelfHandlingForm):
class EditFlavor(CreateFlavor): class EditFlavor(CreateFlavor):
flavor_id = forms.IntegerField(widget=forms.widgets.HiddenInput) flavor_id = forms.CharField(widget=forms.widgets.HiddenInput)
def clean_name(self): def clean_name(self):
return self.cleaned_data['name'] return self.cleaned_data['name']
@ -92,16 +90,14 @@ class EditFlavor(CreateFlavor):
# This is in the same try/except block as the delete call # This is in the same try/except block as the delete call
# because if the delete fails the API will error out because # because if the delete fails the API will error out because
# active flavors can't have the same name. # active flavors can't have the same name.
new_flavor_id = uuid.uuid4()
flavor = api.nova.flavor_create(request, flavor = api.nova.flavor_create(request,
data['name'], data['name'],
data['memory_mb'], data['memory_mb'],
data['vcpus'], data['vcpus'],
data['disk_gb'], data['disk_gb'],
new_flavor_id,
ephemeral=data['eph_gb']) ephemeral=data['eph_gb'])
if (len(extras_dict) > 0): 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'] msg = _('Updated flavor "%s".') % data['name']
messages.success(request, msg) messages.success(request, msg)
return flavor return flavor

View File

@ -21,7 +21,6 @@ class FlavorsTests(test.BaseAdminViewTests):
flavor.ram, flavor.ram,
flavor.vcpus, flavor.vcpus,
flavor.disk, flavor.disk,
IsA(uuid.uuid4()),
ephemeral=eph).AndReturn(flavor) ephemeral=eph).AndReturn(flavor)
api.nova.flavor_list(IsA(http.HttpRequest)) api.nova.flavor_list(IsA(http.HttpRequest))
self.mox.ReplayAll() self.mox.ReplayAll()
@ -55,15 +54,14 @@ class FlavorsTests(test.BaseAdminViewTests):
# POST # POST
api.nova.flavor_get(IsA(http.HttpRequest), flavor.id).AndReturn(flavor) 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) .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), api.nova.flavor_create(IsA(http.HttpRequest),
flavor.name, flavor.name,
flavor.ram, flavor.ram,
flavor.vcpus + 1, flavor.vcpus + 1,
flavor.disk, flavor.disk,
IsA(uuid.uuid4()),
ephemeral=eph).AndReturn(flavor) ephemeral=eph).AndReturn(flavor)
self.mox.ReplayAll() self.mox.ReplayAll()

View File

@ -14,6 +14,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import uuid
from django import http from django import http
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.datastructures import SortedDict from django.utils.datastructures import SortedDict
@ -76,10 +78,10 @@ class InstanceViewTest(test.BaseAdminViewTests):
servers = self.servers.list() servers = self.servers.list()
flavors = self.flavors.list() flavors = self.flavors.list()
tenants = self.tenants.list() tenants = self.tenants.list()
max_id = max([int(flavor.id) for flavor in flavors]) # UUIDs generated using indexes are unlikely to match
for server in servers: # any of existing flavor ids and are guaranteed to be deterministic.
max_id += 1 for i, server in enumerate(servers):
server.flavor["id"] = max_id server.flavor['id'] = str(uuid.UUID(int=i))
api.nova.server_list(IsA(http.HttpRequest), api.nova.server_list(IsA(http.HttpRequest),
all_tenants=True).AndReturn(servers) all_tenants=True).AndReturn(servers)

View File

@ -18,6 +18,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import uuid
from django import http from django import http
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.http import urlencode from django.utils.http import urlencode
@ -90,10 +92,10 @@ class InstanceTests(test.TestCase):
def test_index_flavor_get_exception(self): def test_index_flavor_get_exception(self):
servers = self.servers.list() servers = self.servers.list()
flavors = self.flavors.list() flavors = self.flavors.list()
max_id = max([int(flavor.id) for flavor in flavors]) # UUIDs generated using indexes are unlikely to match
for server in servers: # any of existing flavor ids and are guaranteed to be deterministic.
max_id += 1 for i, server in enumerate(servers):
server.flavor["id"] = max_id server.flavor['id'] = str(uuid.UUID(int=i))
api.server_list(IsA(http.HttpRequest)).AndReturn(servers) api.server_list(IsA(http.HttpRequest)).AndReturn(servers)
api.flavor_list(IsA(http.HttpRequest)).AndReturn(flavors) api.flavor_list(IsA(http.HttpRequest)).AndReturn(flavors)

View File

@ -198,14 +198,14 @@ def data(TEST):
# Flavors # Flavors
flavor_1 = flavors.Flavor(flavors.FlavorManager(None), flavor_1 = flavors.Flavor(flavors.FlavorManager(None),
{'id': "1", {'id': "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
'name': 'm1.tiny', 'name': 'm1.tiny',
'vcpus': 1, 'vcpus': 1,
'disk': 0, 'disk': 0,
'ram': 512, 'ram': 512,
'OS-FLV-EXT-DATA:ephemeral': 0}) 'OS-FLV-EXT-DATA:ephemeral': 0})
flavor_2 = flavors.Flavor(flavors.FlavorManager(None), flavor_2 = flavors.Flavor(flavors.FlavorManager(None),
{'id': "2", {'id': "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
'name': 'm1.massive', 'name': 'm1.massive',
'vcpus': 1000, 'vcpus': 1000,
'disk': 1024, 'disk': 1024,

View File

@ -6,7 +6,7 @@ set -o errexit
# Increment me any time the environment should be rebuilt. # Increment me any time the environment should be rebuilt.
# This includes dependncy changes, directory renames, etc. # This includes dependncy changes, directory renames, etc.
# Simple integer secuence: 1, 2, 3... # Simple integer secuence: 1, 2, 3...
environment_version=28 environment_version=29
#--------------------------------------------------------# #--------------------------------------------------------#
function usage { function usage {

View File

@ -6,7 +6,7 @@ netaddr
python-cinderclient python-cinderclient
python-glanceclient<2 python-glanceclient<2
python-keystoneclient python-keystoneclient
python-novaclient python-novaclient>=2.10.0,<3
python-quantumclient>=2.0 python-quantumclient>=2.0
python-swiftclient>1.1,<2 python-swiftclient>1.1,<2
pytz pytz