Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixes bug 1086290

https://bugs.launchpad.net/horizon/+bug/1086290,
edit-flavor broken when flavor has extra specs.
Includes unittest for the same, and modified mock data to
to include extra-specs
Change-Id: I286d97568daff26bbd03418b2ea0b808caceadba
  • Loading branch information...
commit 95a034ae6295cf20e73c9857ba438e1da808bb8f 1 parent e0c43a4
@mkbhanda mkbhanda authored
View
13 openstack_dashboard/api/nova.py
@@ -195,9 +195,14 @@ def server_vnc_console(request, instance_id, console_type='novnc'):
console_type)['console'])
-def flavor_create(request, name, memory, vcpu, disk, ephemeral=0, swap=0):
- return novaclient(request).flavors.create(name, memory, vcpu, disk,
- ephemeral=ephemeral, swap=swap)
+def flavor_create(request, name, memory, vcpu, disk, ephemeral=0, swap=0,
+ metadata=None):
+ flavor = novaclient(request).flavors.create(name, memory, vcpu, disk,
+ ephemeral=ephemeral,
+ swap=swap)
+ if (metadata):
+ flavor_extra_set(request, flavor.id, metadata)
+ return flavor
def flavor_delete(request, flavor_id):
@@ -233,6 +238,8 @@ def flavor_extra_delete(request, flavor_id, keys):
def flavor_extra_set(request, flavor_id, metadata):
"""Set the flavor extra spec keys."""
flavor = novaclient(request).flavors.get(flavor_id)
+ if (not metadata): # not a way to delete keys
+ return None
return flavor.set_keys(metadata)
View
11 openstack_dashboard/dashboards/admin/flavors/extras/tests.py
@@ -9,13 +9,12 @@
class FlavorExtrasTests(test.BaseAdminViewTests):
+ @test.create_stubs({api.nova: ('flavor_get_extras',
+ 'flavor_get'), })
def test_list_extras_when_none_exists(self):
flavor = self.flavors.first()
extras = [api.FlavorExtraSpec(flavor.id, 'k1', 'v1')]
- self.mox.StubOutWithMock(api.nova, 'flavor_get')
- self.mox.StubOutWithMock(api.nova, 'flavor_get_extras')
-
# GET -- to determine correctness of output
api.nova.flavor_get(IsA(http.HttpRequest), flavor.id).AndReturn(flavor)
api.nova.flavor_get_extras(IsA(http.HttpRequest),
@@ -26,6 +25,7 @@ def test_list_extras_when_none_exists(self):
self.assertEqual(resp.status_code, 200)
self.assertTemplateUsed(resp, "admin/flavors/extras/index.html")
+ @test.create_stubs({api.nova: ('flavor_extra_set', ), })
def test_extra_create_post(self):
flavor = self.flavors.first()
create_url = reverse('horizon:admin:flavors:extras:create',
@@ -33,8 +33,6 @@ def test_extra_create_post(self):
index_url = reverse('horizon:admin:flavors:extras:index',
args=[flavor.id])
- self.mox.StubOutWithMock(api.nova, 'flavor_extra_set')
-
# GET to display the flavor_name
api.nova.flavor_extra_set(IsA(http.HttpRequest),
flavor.id,
@@ -49,13 +47,12 @@ def test_extra_create_post(self):
self.assertMessageCount(success=1)
self.assertRedirectsNoFollow(resp, index_url)
+ @test.create_stubs({api.nova: ('flavor_get', ), })
def test_extra_create_get(self):
flavor = self.flavors.first()
create_url = reverse('horizon:admin:flavors:extras:create',
args=[flavor.id])
- self.mox.StubOutWithMock(api.nova, 'flavor_get')
-
api.nova.flavor_get(IsA(http.HttpRequest), flavor.id).AndReturn(flavor)
self.mox.ReplayAll()
View
6 openstack_dashboard/dashboards/admin/flavors/forms.py
@@ -85,7 +85,9 @@ def handle(self, request, data):
flavor_id = data['flavor_id']
# grab any existing extra specs, because flavor edit currently
# implemented as a delete followed by a create
- extras_dict = api.nova.flavor_get_extras(self.request, flavor_id)
+ extras_dict = api.nova.flavor_get_extras(self.request,
+ flavor_id,
+ raw=True)
# First mark the existing flavor as deleted.
api.nova.flavor_delete(request, data['flavor_id'])
# Then create a new flavor with the same name but a new ID.
@@ -99,7 +101,7 @@ def handle(self, request, data):
data['disk_gb'],
ephemeral=data['eph_gb'],
swap=data['swap_mb'])
- if (len(extras_dict) > 0):
+ if (extras_dict):
api.nova.flavor_extra_set(request, flavor.id, extras_dict)
msg = _('Updated flavor "%s".') % data['name']
messages.success(request, msg)
View
109 openstack_dashboard/dashboards/admin/flavors/tests.py
@@ -6,14 +6,14 @@
from openstack_dashboard import api
from openstack_dashboard.test import helpers as test
+from novaclient.v1_1 import flavors
class FlavorsTests(test.BaseAdminViewTests):
+ @test.create_stubs({api.nova: ('flavor_list', 'flavor_create'), })
def test_create_new_flavor_when_none_exist(self):
flavor = self.flavors.first()
eph = getattr(flavor, 'OS-FLV-EXT-DATA:ephemeral')
- self.mox.StubOutWithMock(api.nova, 'flavor_list')
- self.mox.StubOutWithMock(api.nova, 'flavor_create')
# no pre-existing flavors
api.nova.flavor_create(IsA(http.HttpRequest),
@@ -21,7 +21,7 @@ def test_create_new_flavor_when_none_exist(self):
flavor.ram,
flavor.vcpus,
flavor.disk,
- swap=flavor.swap or 0,
+ swap=flavor.swap,
ephemeral=eph).AndReturn(flavor)
api.nova.flavor_list(IsA(http.HttpRequest))
self.mox.ReplayAll()
@@ -35,37 +35,108 @@ def test_create_new_flavor_when_none_exist(self):
'vcpus': flavor.vcpus,
'memory_mb': flavor.ram,
'disk_gb': flavor.disk,
- 'swap_mb': flavor.swap or 0,
+ 'swap_mb': flavor.swap,
'eph_gb': eph}
resp = self.client.post(url, data)
self.assertRedirectsNoFollow(resp,
reverse("horizon:admin:flavors:index"))
+ # keeping the 2 edit tests separate to aid debug breaks
+ @test.create_stubs({api.nova: ('flavor_list',
+ 'flavor_create',
+ 'flavor_delete',
+ 'flavor_get_extras',
+ 'flavor_get'), })
def test_edit_flavor(self):
- flavor = self.flavors.first()
+ flavor = self.flavors.first() # has no extra specs
eph = getattr(flavor, 'OS-FLV-EXT-DATA:ephemeral')
- extras = {}
- self.mox.StubOutWithMock(api.nova, 'flavor_list')
- self.mox.StubOutWithMock(api.nova, 'flavor_get_extras')
- self.mox.StubOutWithMock(api.nova, 'flavor_get')
- self.mox.StubOutWithMock(api.nova, 'flavor_delete')
- self.mox.StubOutWithMock(api.nova, 'flavor_create')
+ extra_specs = getattr(flavor, 'extra_specs')
+ new_flavor = flavors.Flavor(flavors.FlavorManager(None),
+ {'id':
+ "cccccccc-cccc-cccc-cccc-cccccccccccc",
+ 'name': flavor.name,
+ 'vcpus': flavor.vcpus + 1,
+ 'disk': flavor.disk,
+ 'ram': flavor.ram,
+ 'swap': 0,
+ 'OS-FLV-EXT-DATA:ephemeral': eph,
+ 'extra_specs': extra_specs})
+ # GET
+ api.nova.flavor_get(IsA(http.HttpRequest), flavor.id).AndReturn(flavor)
+
+ # POST
+ api.nova.flavor_get(IsA(http.HttpRequest), flavor.id).AndReturn(flavor)
+ api.nova.flavor_get_extras(IsA(http.HttpRequest), flavor.id, raw=True)\
+ .AndReturn(extra_specs)
+ api.nova.flavor_delete(IsA(http.HttpRequest), flavor.id)
+ api.nova.flavor_create(IsA(http.HttpRequest),
+ new_flavor.name,
+ new_flavor.ram,
+ new_flavor.vcpus,
+ new_flavor.disk,
+ swap=flavor.swap,
+ ephemeral=eph).AndReturn(new_flavor)
+ self.mox.ReplayAll()
+
+ # get_test
+ url = reverse('horizon:admin:flavors:edit', args=[flavor.id])
+ resp = self.client.get(url)
+ self.assertEqual(resp.status_code, 200)
+ self.assertTemplateUsed(resp, "admin/flavors/edit.html")
+ # post test
+ data = {'flavor_id': flavor.id,
+ 'name': flavor.name,
+ 'vcpus': flavor.vcpus + 1,
+ 'memory_mb': flavor.ram,
+ 'disk_gb': flavor.disk,
+ 'swap_mb': flavor.swap,
+ 'eph_gb': eph}
+ resp = self.client.post(url, data)
+ self.assertNoFormErrors(resp)
+ self.assertMessageCount(success=1)
+ self.assertRedirectsNoFollow(resp,
+ reverse("horizon:admin:flavors:index"))
+
+ @test.create_stubs({api.nova: ('flavor_list',
+ 'flavor_create',
+ 'flavor_delete',
+ 'flavor_get_extras',
+ 'flavor_extra_set',
+ 'flavor_get'), })
+ def test_edit_flavor_with_extra_specs(self):
+ flavor = self.flavors.list()[1] # the second element has extra specs
+ eph = getattr(flavor, 'OS-FLV-EXT-DATA:ephemeral')
+ extra_specs = getattr(flavor, 'extra_specs')
+ new_vcpus = flavor.vcpus + 1
+ new_flavor = flavors.Flavor(flavors.FlavorManager(None),
+ {'id':
+ "cccccccc-cccc-cccc-cccc-cccccccccccc",
+ 'name': flavor.name,
+ 'vcpus': new_vcpus,
+ 'disk': flavor.disk,
+ 'ram': flavor.ram,
+ 'swap': flavor.swap,
+ 'OS-FLV-EXT-DATA:ephemeral': eph,
+ 'extra_specs': extra_specs})
# GET
api.nova.flavor_get(IsA(http.HttpRequest), flavor.id).AndReturn(flavor)
# POST
api.nova.flavor_get(IsA(http.HttpRequest), flavor.id).AndReturn(flavor)
- api.nova.flavor_get_extras(IsA(http.HttpRequest), flavor.id)\
- .AndReturn(extras)
+ api.nova.flavor_get_extras(IsA(http.HttpRequest), flavor.id, raw=True)\
+ .AndReturn(extra_specs)
api.nova.flavor_delete(IsA(http.HttpRequest), flavor.id)
api.nova.flavor_create(IsA(http.HttpRequest),
flavor.name,
flavor.ram,
- flavor.vcpus + 1,
+ new_vcpus,
flavor.disk,
- swap=flavor.swap or 0,
- ephemeral=eph).AndReturn(flavor)
+ swap=flavor.swap,
+ ephemeral=eph).AndReturn(new_flavor)
+ api.nova.flavor_extra_set(IsA(http.HttpRequest),
+ new_flavor.id,
+ extra_specs)
self.mox.ReplayAll()
#get_test
@@ -77,11 +148,13 @@ def test_edit_flavor(self):
#post test
data = {'flavor_id': flavor.id,
'name': flavor.name,
- 'vcpus': flavor.vcpus + 1,
+ 'vcpus': new_vcpus,
'memory_mb': flavor.ram,
'disk_gb': flavor.disk,
- 'swap_mb': flavor.swap or 0,
+ 'swap_mb': flavor.swap,
'eph_gb': eph}
resp = self.client.post(url, data)
+ self.assertNoFormErrors(resp)
+ self.assertMessageCount(success=1)
self.assertRedirectsNoFollow(resp,
reverse("horizon:admin:flavors:index"))
View
2  openstack_dashboard/test/test_data/nova_data.py
@@ -204,6 +204,7 @@ def data(TEST):
'disk': 0,
'ram': 512,
'swap': 0,
+ 'extra_specs': {},
'OS-FLV-EXT-DATA:ephemeral': 0})
flavor_2 = flavors.Flavor(flavors.FlavorManager(None),
{'id': "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
@@ -212,6 +213,7 @@ def data(TEST):
'disk': 1024,
'ram': 10000,
'swap': 0,
+ 'extra_specs': {'Trusted': True, 'foo': 'bar'},
'OS-FLV-EXT-DATA:ephemeral': 2048})
TEST.flavors.add(flavor_1, flavor_2)
Please sign in to comment.
Something went wrong with that request. Please try again.