cleanup resources in setUpClass if exception raised
Resources created would not be cleanup if exception raised
in setUpClass.
This patch adds a new decorator to wrap setUpClass for
catching the exception in setUpClass and cleanup resources
using tearDownClass().
Use the decorator in the following test classes:
FloatingIPsTestJSON
ImagesMetadataTestJSON
ListServerFiltersTestJSON
Change-Id: Ia20ebd2a5d1b5ecbd5e8b21e51e7c2ee4c99fbd5
Closes-Bug: #1285509
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions.py b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
index c0f7af0..abd8a4c 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -24,10 +24,11 @@
floating_ip = None
@classmethod
+ @test.safe_setup
def setUpClass(cls):
super(FloatingIPsTestJSON, cls).setUpClass()
cls.client = cls.floating_ips_client
- #cls.servers_client = cls.servers_client
+ cls.floating_ip_id = None
# Server creation
resp, server = cls.create_test_server(wait_until='ACTIVE')
@@ -40,7 +41,8 @@
@classmethod
def tearDownClass(cls):
# Deleting the floating IP which is created in this method
- resp, body = cls.client.delete_floating_ip(cls.floating_ip_id)
+ if cls.floating_ip_id:
+ resp, body = cls.client.delete_floating_ip(cls.floating_ip_id)
super(FloatingIPsTestJSON, cls).tearDownClass()
@test.attr(type='gate')
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index ad211ce..91eb4c5 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -16,7 +16,7 @@
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import config
-from tempest.test import attr
+from tempest import test
CONF = config.CONF
@@ -24,14 +24,15 @@
class ImagesMetadataTestJSON(base.BaseV2ComputeTest):
@classmethod
+ @test.safe_setup
def setUpClass(cls):
super(ImagesMetadataTestJSON, cls).setUpClass()
if not CONF.service_available.glance:
skip_msg = ("%s skipped as glance is not available" % cls.__name__)
raise cls.skipException(skip_msg)
- cls.servers_client = cls.servers_client
cls.client = cls.images_client
+ cls.image_id = None
resp, server = cls.create_test_server(wait_until='ACTIVE')
cls.server_id = server['id']
@@ -45,7 +46,8 @@
@classmethod
def tearDownClass(cls):
- cls.client.delete_image(cls.image_id)
+ if cls.image_id:
+ cls.client.delete_image(cls.image_id)
super(ImagesMetadataTestJSON, cls).tearDownClass()
def setUp(self):
@@ -54,14 +56,14 @@
resp, _ = self.client.set_image_metadata(self.image_id, meta)
self.assertEqual(resp.status, 200)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_list_image_metadata(self):
# All metadata key/value pairs for an image should be returned
resp, resp_metadata = self.client.list_image_metadata(self.image_id)
expected = {'key1': 'value1', 'key2': 'value2'}
self.assertEqual(expected, resp_metadata)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_set_image_metadata(self):
# The metadata for the image should match the new values
req_metadata = {'meta2': 'value2', 'meta3': 'value3'}
@@ -71,7 +73,7 @@
resp, resp_metadata = self.client.list_image_metadata(self.image_id)
self.assertEqual(req_metadata, resp_metadata)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_update_image_metadata(self):
# The metadata for the image should match the updated values
req_metadata = {'key1': 'alt1', 'key3': 'value3'}
@@ -82,14 +84,14 @@
expected = {'key1': 'alt1', 'key2': 'value2', 'key3': 'value3'}
self.assertEqual(expected, resp_metadata)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_image_metadata_item(self):
# The value for a specific metadata key should be returned
resp, meta = self.client.get_image_metadata_item(self.image_id,
'key2')
self.assertEqual('value2', meta['key2'])
- @attr(type='gate')
+ @test.attr(type='gate')
def test_set_image_metadata_item(self):
# The value provided for the given meta item should be set for
# the image
@@ -100,7 +102,7 @@
expected = {'key1': 'alt', 'key2': 'value2'}
self.assertEqual(expected, resp_metadata)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_delete_image_metadata_item(self):
# The metadata value/key pair should be deleted from the image
resp, body = self.client.delete_image_metadata_item(self.image_id,
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 837114c..f0913f1 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -26,6 +26,7 @@
class ListServerFiltersTestJSON(base.BaseV2ComputeTest):
@classmethod
+ @test.safe_setup
def setUpClass(cls):
super(ListServerFiltersTestJSON, cls).setUpClass()
cls.client = cls.servers_client
diff --git a/tempest/api/compute/v3/servers/test_list_server_filters.py b/tempest/api/compute/v3/servers/test_list_server_filters.py
index ec31e8e..2cb176c 100644
--- a/tempest/api/compute/v3/servers/test_list_server_filters.py
+++ b/tempest/api/compute/v3/servers/test_list_server_filters.py
@@ -26,6 +26,7 @@
class ListServerFiltersV3Test(base.BaseV3ComputeTest):
@classmethod
+ @test.safe_setup
def setUpClass(cls):
super(ListServerFiltersV3Test, cls).setUpClass()
cls.client = cls.servers_client
diff --git a/tempest/test.py b/tempest/test.py
index c6e3d6e..9332f93 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -63,6 +63,25 @@
return decorator
+def safe_setup(f):
+ """A decorator used to wrap the setUpClass for cleaning up resources
+ when setUpClass failed.
+ """
+
+ def decorator(cls):
+ try:
+ f(cls)
+ except Exception as se:
+ LOG.exception("setUpClass failed: %s" % se)
+ try:
+ cls.tearDownClass()
+ except Exception as te:
+ LOG.exception("tearDownClass failed: %s" % te)
+ raise se
+
+ return decorator
+
+
def services(*args, **kwargs):
"""A decorator used to set an attr for each service used in a test case