Prevents flavors to be deleted when reusing a name
Adds an extra check to the EditFlavor form in order to avoid losing the flavor if an existing name is setted as the new name. This control is needed because the current edit implementation is based in a delete-create action. Change-Id: I4251c64fa4719831a1ed949bf95349a350dd303d Fixes: bug #1133254
This commit is contained in:
parent
c157d95eb2
commit
c6d6557cd2
@ -94,6 +94,27 @@ class EditFlavor(CreateFlavor):
|
|||||||
def clean_name(self):
|
def clean_name(self):
|
||||||
return self.cleaned_data['name']
|
return self.cleaned_data['name']
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
cleaned_data = super(EditFlavor, self).clean()
|
||||||
|
name = cleaned_data.get('name')
|
||||||
|
flavor_id = cleaned_data.get('flavor_id')
|
||||||
|
try:
|
||||||
|
flavors = api.nova.flavor_list(self.request)
|
||||||
|
except:
|
||||||
|
flavors = []
|
||||||
|
msg = _('Unable to get flavor list')
|
||||||
|
exceptions.check_message(["Connection", "refused"], msg)
|
||||||
|
raise
|
||||||
|
# Check if there is no flavor with the same name
|
||||||
|
if flavors is not None:
|
||||||
|
for flavor in flavors:
|
||||||
|
if flavor.name == name and int(flavor.id) != flavor_id:
|
||||||
|
raise forms.ValidationError(
|
||||||
|
_('The name "%s" is already used by another flavor.')
|
||||||
|
% name
|
||||||
|
)
|
||||||
|
return cleaned_data
|
||||||
|
|
||||||
def handle(self, request, data):
|
def handle(self, request, data):
|
||||||
try:
|
try:
|
||||||
# First mark the existing flavor as deleted.
|
# First mark the existing flavor as deleted.
|
||||||
|
@ -53,6 +53,7 @@ class FlavorsTests(test.BaseAdminViewTests):
|
|||||||
api.nova.flavor_get(IsA(http.HttpRequest), flavor.id).AndReturn(flavor)
|
api.nova.flavor_get(IsA(http.HttpRequest), flavor.id).AndReturn(flavor)
|
||||||
|
|
||||||
# POST
|
# POST
|
||||||
|
api.nova.flavor_list(IsA(http.HttpRequest))
|
||||||
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_delete(IsA(http.HttpRequest), int(flavor.id))
|
api.nova.flavor_delete(IsA(http.HttpRequest), int(flavor.id))
|
||||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||||
@ -80,3 +81,36 @@ class FlavorsTests(test.BaseAdminViewTests):
|
|||||||
resp = self.client.post(url, data)
|
resp = self.client.post(url, data)
|
||||||
self.assertRedirectsNoFollow(resp,
|
self.assertRedirectsNoFollow(resp,
|
||||||
reverse("horizon:syspanel:flavors:index"))
|
reverse("horizon:syspanel:flavors:index"))
|
||||||
|
|
||||||
|
def test_edit_flavor_set_existing_name(self):
|
||||||
|
flavor_a = self.flavors.list()[0]
|
||||||
|
flavor_b = self.flavors.list()[1]
|
||||||
|
eph = getattr(flavor_a, 'OS-FLV-EXT-DATA:ephemeral')
|
||||||
|
self.mox.StubOutWithMock(api.nova, 'flavor_list')
|
||||||
|
self.mox.StubOutWithMock(api.nova, 'flavor_get')
|
||||||
|
|
||||||
|
# GET
|
||||||
|
api.nova.flavor_get(IsA(http.HttpRequest), flavor_a.id) \
|
||||||
|
.AndReturn(flavor_a)
|
||||||
|
|
||||||
|
# POST
|
||||||
|
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||||
|
.AndReturn(self.flavors.list())
|
||||||
|
api.nova.flavor_get(IsA(http.HttpRequest),
|
||||||
|
flavor_a.id).AndReturn(flavor_a)
|
||||||
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
url = reverse('horizon:syspanel:flavors:edit', args=[flavor_a.id])
|
||||||
|
resp = self.client.get(url)
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
self.assertTemplateUsed(resp, "syspanel/flavors/edit.html")
|
||||||
|
|
||||||
|
data = {'flavor_id': flavor_a.id,
|
||||||
|
'name': flavor_b.name,
|
||||||
|
'vcpus': flavor_a.vcpus + 1,
|
||||||
|
'memory_mb': flavor_a.ram,
|
||||||
|
'disk_gb': flavor_a.disk,
|
||||||
|
'eph_gb': eph}
|
||||||
|
resp = self.client.post(url, data)
|
||||||
|
self.assertFormErrors(resp, 1, 'The name "m1.massive" '
|
||||||
|
'is already used by another flavor.')
|
||||||
|
Loading…
Reference in New Issue
Block a user