Minor fixes and docstrings updates
Change-Id: Ibc6c1da236cdfdc1dbb5ad65004247d1696f3ec3
diff --git a/tempest/services/nova/json/flavors_client.py b/tempest/services/nova/json/flavors_client.py
index 84fa9ff..bd77484 100644
--- a/tempest/services/nova/json/flavors_client.py
+++ b/tempest/services/nova/json/flavors_client.py
@@ -39,3 +39,27 @@
resp, body = self.get("flavors/%s" % str(flavor_id))
body = json.loads(body)
return resp, body['flavor']
+
+ def create_flavor(self, name, ram, vcpus, disk, ephemeral, flavor_id,
+ swap, rxtx):
+ """Creates a new flavor or instance type"""
+ post_body = {
+ 'name': name,
+ 'ram': ram,
+ 'vcpus': vcpus,
+ 'disk': disk,
+ 'OS-FLV-EXT-DATA:ephemeral': ephemeral,
+ 'id': flavor_id,
+ 'swap': swap,
+ 'rxtx_factor': rxtx
+ }
+
+ post_body = json.dumps({'flavor': post_body})
+ resp, body = self.post('flavors', post_body, self.headers)
+
+ body = json.loads(body)
+ return resp, body['flavor']
+
+ def delete_flavor(self, flavor_id):
+ """Deletes the given flavor"""
+ return self.delete("flavors/%s" % str(flavor_id))
diff --git a/tempest/tests/compute/admin/__init__.py b/tempest/tests/compute/admin/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/tests/compute/admin/__init__.py
diff --git a/tempest/tests/compute/admin/test_flavors.py b/tempest/tests/compute/admin/test_flavors.py
new file mode 100644
index 0000000..377781b
--- /dev/null
+++ b/tempest/tests/compute/admin/test_flavors.py
@@ -0,0 +1,111 @@
+from nose.plugins.attrib import attr
+from nose import SkipTest
+import tempest.config
+from tempest import exceptions
+from tempest import openstack
+from tempest.tests.base_compute_test import BaseComputeTest
+
+
+class FlavorsAdminTest(BaseComputeTest):
+
+ """
+ Tests Flavors API Create and Delete that require admin privileges
+ """
+
+ @classmethod
+ def setUpClass(cls):
+ cls.config = tempest.config.TempestConfig()
+ cls.admin_username = cls.config.compute_admin.username
+ cls.admin_password = cls.config.compute_admin.password
+ cls.admin_tenant = cls.config.compute_admin.tenant_name
+
+ if not(cls.admin_username and cls.admin_password and cls.admin_tenant):
+ raise SkipTest("Missing Admin credentials in configuration")
+ else:
+ cls.admin_os = openstack.AdminManager()
+ cls.admin_client = cls.admin_os.flavors_client
+ cls.flavor_name = 'test_flavor'
+ cls.ram = 512
+ cls.vcpus = 1
+ cls.disk = 10
+ cls.ephemeral = 10
+ cls.new_flavor_id = 1234
+ cls.swap = 1024
+ cls.rxtx = 1
+
+ @attr(type='positive')
+ def test_create_flavor(self):
+ """Create a flavor and ensure it is listed
+ This operation requires the user to have 'admin' role"""
+
+ #Create the flavor
+ resp, flavor = self.admin_client.create_flavor(self.flavor_name,
+ self.ram, self.vcpus,
+ self.disk,
+ self.ephemeral,
+ self.new_flavor_id,
+ self.swap, self.rxtx)
+ self.assertEqual(200, resp.status)
+ self.assertEqual(flavor['name'], self.flavor_name)
+ self.assertEqual(flavor['vcpus'], self.vcpus)
+ self.assertEqual(flavor['disk'], self.disk)
+ self.assertEqual(flavor['ram'], self.ram)
+ self.assertEqual(int(flavor['id']), self.new_flavor_id)
+ self.assertEqual(flavor['swap'], self.swap)
+ self.assertEqual(flavor['rxtx_factor'], self.rxtx)
+ self.assertEqual(flavor['OS-FLV-EXT-DATA:ephemeral'], self.ephemeral)
+
+ #Verify flavor is retrieved
+ resp, flavor = self.admin_client.get_flavor_details(self.new_flavor_id)
+ self.assertEqual(resp.status, 200)
+ self.assertEqual(flavor['name'], self.flavor_name)
+
+ #Delete the flavor
+ resp, body = self.admin_client.delete_flavor(flavor['id'])
+ self.assertEqual(resp.status, 202)
+
+ @attr(type='positive')
+ def test_create_flavor_verify_entry_in_list_details(self):
+ """Create a flavor and ensure it's details are listed
+ This operation requires the user to have 'admin' role"""
+
+ #Create the flavor
+ resp, flavor = self.admin_client.create_flavor(self.flavor_name,
+ self.ram, self.vcpus,
+ self.disk,
+ self.ephemeral,
+ self.new_flavor_id,
+ self.swap, self.rxtx)
+ flag = False
+ #Verify flavor is retrieved
+ resp, flavors = self.admin_client.list_flavors_with_detail()
+ self.assertEqual(resp.status, 200)
+ for flavor in flavors:
+ if flavor['name'] == self.flavor_name:
+ flag = True
+ self.assertTrue(flag)
+
+ #Delete the flavor
+ resp, body = self.admin_client.delete_flavor(self.new_flavor_id)
+ self.assertEqual(resp.status, 202)
+
+ @attr(type='negative')
+ def test_get_flavor_details_for_deleted_flavor(self):
+ """Delete a flavor and ensure it is not listed"""
+
+ # Create a test flavor
+ resp, flavor = self.admin_client.create_flavor(self.flavor_name,
+ self.ram,
+ self.vcpus, self.disk,
+ self.ephemeral,
+ self.new_flavor_id,
+ self.swap, self.rxtx)
+ self.assertEquals(200, resp.status)
+
+ # Delete the flavor
+ resp, _ = self.admin_client.delete_flavor(self.new_flavor_id)
+ self.assertEqual(resp.status, 202)
+
+ # Get deleted flavor details
+ self.assertRaises(exceptions.NotFound,
+ self.admin_client.get_flavor_details, self.new_flavor_id)
diff --git a/tempest/tests/test_flavors.py b/tempest/tests/test_flavors.py
index 34aa68c..d5d598f 100644
--- a/tempest/tests/test_flavors.py
+++ b/tempest/tests/test_flavors.py
@@ -1,8 +1,5 @@
-import unittest2 as unittest
from nose.plugins.attrib import attr
from tempest import exceptions
-from tempest import openstack
-import tempest.config
from base_compute_test import BaseComputeTest
@@ -11,13 +8,12 @@
@classmethod
def setUpClass(cls):
cls.client = cls.flavors_client
- cls.flavor_id = cls.flavor_ref
@attr(type='smoke')
def test_list_flavors(self):
"""List of all flavors should contain the expected flavor"""
resp, flavors = self.client.list_flavors()
- resp, flavor = self.client.get_flavor_details(self.flavor_id)
+ resp, flavor = self.client.get_flavor_details(self.flavor_ref)
flavor_min_detail = {'id': flavor['id'], 'links': flavor['links'],
'name': flavor['name']}
self.assertTrue(flavor_min_detail in flavors)
@@ -26,14 +22,14 @@
def test_list_flavors_with_detail(self):
"""Detailed list of all flavors should contain the expected flavor"""
resp, flavors = self.client.list_flavors_with_detail()
- resp, flavor = self.client.get_flavor_details(self.flavor_id)
+ resp, flavor = self.client.get_flavor_details(self.flavor_ref)
self.assertTrue(flavor in flavors)
@attr(type='smoke')
def test_get_flavor(self):
"""The expected flavor details should be returned"""
- resp, flavor = self.client.get_flavor_details(self.flavor_id)
- self.assertEqual(self.flavor_id, str(flavor['id']))
+ resp, flavor = self.client.get_flavor_details(self.flavor_ref)
+ self.assertEqual(self.flavor_ref, str(flavor['id']))
@attr(type='negative')
def test_get_non_existant_flavor(self):
@@ -120,3 +116,10 @@
params = {'minRam': flavors[1]['ram']}
resp, flavors = self.client.list_flavors(params)
self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
+
+ @attr(type='negative')
+ def test_get_flavor_details_for_invalid_flavor_id(self):
+ """Ensure 404 returned for non-existant flavor ID"""
+
+ self.assertRaises(exceptions.NotFound, self.client.get_flavor_details,
+ 9999)