Added filter tests to list images tests, addresses lp bug 900088
* Added tests for all filters except by id and changes-since
* Also improved exception handling to include server uuid for troubleshooting
Change-Id: I9a69390e178bb6bb9244f7000a7e01dd3e530e73
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index bcdc758..18f86a7 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -107,6 +107,13 @@
if resp.status in (500, 501):
body = json.loads(body)
- raise exceptions.ComputeFault(body['computeFault']['message'])
+ #I'm seeing both computeFault and cloudServersFault come back.
+ #Will file a bug to fix, but leave as is for now.
+
+ if 'cloudServersFault' in body:
+ message = body['cloudServersFault']['message']
+ else:
+ message = body['computeFault']['message']
+ raise exceptions.ComputeFault(message)
return resp, body
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index 180f13a..16d6af3 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -1,13 +1,19 @@
class TimeoutException(Exception):
"""Exception on timeout"""
- def __repr__(self):
- return "Request timed out"
+ def __init__(self, message):
+ self.message = message
+
+ def __str__(self):
+ return repr(self.message)
class BuildErrorException(Exception):
- """Exception on server build"""
- def __repr__(self):
- return "Server failed into error status"
+ """Server entered ERROR status unintentionally"""
+ def __init__(self, message):
+ self.message = message
+
+ def __str__(self):
+ return repr(self.message)
class BadRequest(Exception):
diff --git a/tempest/services/nova/json/servers_client.py b/tempest/services/nova/json/servers_client.py
index b3d2ed6..5fac08e 100644
--- a/tempest/services/nova/json/servers_client.py
+++ b/tempest/services/nova/json/servers_client.py
@@ -141,10 +141,13 @@
server_status = body['status']
if(server_status == 'ERROR'):
- raise exceptions.BuildErrorException
+ message = 'Server %s entered ERROR status.' % server_id
+ raise exceptions.BuildErrorException(message)
if (int(time.time()) - start >= self.build_timeout):
- raise exceptions.TimeoutException
+ message = 'Server %s failed to reach ACTIVE status within the \
+ required time (%s s).' % (server_id, self.build_timeout)
+ raise exceptions.TimeoutException(message)
def list_addresses(self, server_id):
"""Lists all addresses for a server"""
diff --git a/tempest/tests/test_list_images.py b/tempest/tests/test_list_images.py
index 0f1f966..d78cf02 100644
--- a/tempest/tests/test_list_images.py
+++ b/tempest/tests/test_list_images.py
@@ -1,8 +1,14 @@
from nose.plugins.attrib import attr
from tempest import openstack
+from tempest.common.utils.data_utils import rand_name
import unittest2 as unittest
+def _parse_image_id(image_ref):
+ temp = image_ref.rsplit('/')
+ return temp[len(temp) - 1]
+
+
class ListImagesTest(unittest.TestCase):
@classmethod
@@ -14,6 +20,40 @@
cls.image_ref = cls.config.env.image_ref
cls.flavor_ref = cls.config.env.flavor_ref
+ name = rand_name('server')
+ resp, cls.server1 = cls.servers_client.create_server(name,
+ cls.image_ref,
+ cls.flavor_ref)
+ cls.servers_client.wait_for_server_status(cls.server1['id'], 'ACTIVE')
+
+ name = rand_name('server')
+ resp, cls.server2 = cls.servers_client.create_server(name,
+ cls.image_ref,
+ cls.flavor_ref)
+ cls.servers_client.wait_for_server_status(cls.server2['id'], 'ACTIVE')
+
+ #Create images to be used in the filter tests
+ image1_name = rand_name('image')
+ resp, body = cls.client.create_image(cls.server1['id'], image1_name)
+ cls.image1_id = _parse_image_id(resp['location'])
+ cls.client.wait_for_image_resp_code(cls.image1_id, 200)
+ cls.client.wait_for_image_status(cls.image1_id, 'ACTIVE')
+ resp, cls.image1 = cls.client.get_image(cls.image1_id)
+
+ image2_name = rand_name('image')
+ resp, body = cls.client.create_image(cls.server1['id'], image2_name)
+ cls.image2_id = _parse_image_id(resp['location'])
+ cls.client.wait_for_image_resp_code(cls.image2_id, 200)
+ cls.client.wait_for_image_status(cls.image2_id, 'ACTIVE')
+ resp, cls.image2 = cls.client.get_image(cls.image2_id)
+
+ image3_name = rand_name('image')
+ resp, body = cls.client.create_image(cls.server2['id'], image3_name)
+ cls.image3_id = _parse_image_id(resp['location'])
+ cls.client.wait_for_image_resp_code(cls.image3_id, 200)
+ cls.client.wait_for_image_status(cls.image3_id, 'ACTIVE')
+ resp, cls.image3 = cls.client.get_image(cls.image3_id)
+
@attr(type='smoke')
def test_get_image(self):
"""Returns the correct details for a single image"""
@@ -27,9 +67,159 @@
found = any([i for i in images if i['id'] == self.image_ref])
self.assertTrue(found)
+ @attr(type='positive')
+ def test_list_images_filter_by_status(self):
+ """
+ The list of images should contain only images with the provided status
+ """
+ params = {'status': 'ACTIVE'}
+ resp, images = self.client.list_images(params)
+
+ self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))
+ self.assertTrue(any([i for i in images if i['id'] == self.image2_id]))
+ self.assertTrue(any([i for i in images if i['id'] == self.image3_id]))
+
+ @attr(type='positive')
+ def test_list_images_filter_by_name(self):
+ """
+ List of all images should contain the expected images filtered by name
+ """
+ params = {'name': self.image1['name']}
+ resp, images = self.client.list_images(params)
+
+ self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))
+ self.assertFalse(any([i for i in images if i['id'] == self.image2_id]))
+ self.assertFalse(any([i for i in images if i['id'] == self.image3_id]))
+
+ @attr(type='positive')
+ def test_list_images_filter_by_server_id(self):
+ """The images should contain images filtered by server id"""
+ params = {'server': self.server1['id']}
+ resp, images = self.client.list_images(params)
+
+ self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))
+ self.assertTrue(any([i for i in images if i['id'] == self.image2_id]))
+ self.assertFalse(any([i for i in images if i['id'] == self.image3_id]))
+
+ @attr(type='positive')
+ def test_list_images_filter_by_server_ref(self):
+ """The list of servers should be filtered by server ref"""
+ params = {'server': self.image3['metadata']['instance_ref']}
+ resp, images = self.client.list_images(params)
+
+ self.assertFalse(any([i for i in images if i['id'] == self.image1_id]))
+ self.assertFalse(any([i for i in images if i['id'] == self.image2_id]))
+ self.assertTrue(any([i for i in images if i['id'] == self.image3_id]))
+
+ @attr(type='positive')
+ def test_list_images_filter_by_type(self):
+ """The list of servers should be filtered by image type"""
+ params = {'type': 'snapshot'}
+ resp, images = self.client.list_images(params)
+
+ self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))
+ self.assertTrue(any([i for i in images if i['id'] == self.image2_id]))
+ self.assertTrue(any([i for i in images if i['id'] == self.image3_id]))
+ self.assertFalse(any([i for i in images if i['id'] == self.image_ref]))
+
+ @attr(type='positive')
+ def test_list_images_limit_results(self):
+ """Verify only the expected number of results are returned"""
+ params = {'limit': '1'}
+ resp, images = self.client.list_images(params)
+ self.assertEqual(1, len(images))
+
+ @attr(type='positive')
+ def test_list_images_filter_by_changes_since(self):
+ """Verify only updated images are returned in the detailed list"""
+
+ #Becoming ACTIVE will modify the updated time
+ #Filter by the image's created time
+ params = {'changes-since': self.image3['created']}
+ resp, images = self.client.list_images(params)
+ found = any([i for i in images if i['id'] == self.image3_id])
+ self.assertTrue(found)
+
@attr(type='smoke')
def test_list_images_with_detail(self):
"""Detailed list of all images should contain the expected image"""
resp, images = self.client.list_images_with_detail()
found = any([i for i in images if i['id'] == self.image_ref])
self.assertTrue(found)
+
+ @attr(type='smoke')
+ def test_list_images_with_detail(self):
+ """Detailed list of all images should contain the expected images"""
+ resp, images = self.client.list_images_with_detail()
+
+ self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))
+ self.assertTrue(any([i for i in images if i['id'] == self.image2_id]))
+ self.assertTrue(any([i for i in images if i['id'] == self.image3_id]))
+
+ @attr(type='positive')
+ def test_list_images_with_detail_filter_by_status(self):
+ """
+ Detailed list of all images should only contain images
+ with the provided status
+ """
+ params = {'status': 'ACTIVE'}
+ resp, images = self.client.list_images_with_detail(params)
+
+ self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))
+ self.assertTrue(any([i for i in images if i['id'] == self.image2_id]))
+ self.assertTrue(any([i for i in images if i['id'] == self.image3_id]))
+
+ @attr(type='positive')
+ def test_list_images_with_detail_filter_by_name(self):
+ """
+ Detailed list of all images should contain the expected
+ images filtered by name
+ """
+ params = {'name': self.image1['name']}
+ resp, images = self.client.list_images_with_detail(params)
+
+ self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))
+ self.assertFalse(any([i for i in images if i['id'] == self.image2_id]))
+ self.assertFalse(any([i for i in images if i['id'] == self.image3_id]))
+
+ @attr(type='positive')
+ def test_list_images_with_detail_limit_results(self):
+ """
+ Verify only the expected number of results (with full details)
+ are returned
+ """
+ params = {'limit': '1'}
+ resp, images = self.client.list_images_with_detail(params)
+ self.assertEqual(1, len(images))
+
+ @attr(type='positive')
+ def test_list_images_with_detail_filter_by_server_ref(self):
+ """Detailed list of servers should be filtered by server ref"""
+ params = {'server': self.image3['metadata']['instance_ref']}
+ resp, images = self.client.list_images_with_detail(params)
+
+ self.assertFalse(any([i for i in images if i['id'] == self.image1_id]))
+ self.assertFalse(any([i for i in images if i['id'] == self.image2_id]))
+ self.assertTrue(any([i for i in images if i['id'] == self.image3_id]))
+
+ @attr(type='positive')
+ def test_list_images_with_detail_filter_by_type(self):
+ """The detailed list of servers should be filtered by image type"""
+ params = {'type': 'snapshot'}
+ resp, images = self.client.list_images_with_detail(params)
+ resp, image4 = self.client.get_image(self.image_ref)
+
+ self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))
+ self.assertTrue(any([i for i in images if i['id'] == self.image2_id]))
+ self.assertTrue(any([i for i in images if i['id'] == self.image3_id]))
+ self.assertFalse(any([i for i in images if i['id'] == self.image_ref]))
+
+ @attr(type='positive')
+ def test_list_images_with_detail_filter_by_changes_since(self):
+ """Verify an update image is returned"""
+
+ #Becoming ACTIVE will modify the updated time
+ #Filter by the image's created time
+ params = {'changes-since': self.image1['created']}
+ resp, images = self.client.list_images_with_detail(params)
+ self.assertTrue(any([i for i in images if i['id'] == self.image1_id]))