Fix cleanup NotImplemented error
tempest cleanup doesn't check if the APIs it uses are
implemented or not. Therefore the patch adds a try
except block preventing tempest cleanup to fail when
some of the APIs are not implemented.
Closes-bug: #1832566
Change-Id: I9ced4af40eb0c2a22e3557caded56045a397d539
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index e6db2e9..f0d7264 100644
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -94,6 +94,8 @@
class TempestCleanup(command.Command):
+ GOT_EXCEPTIONS = []
+
def take_action(self, parsed_args):
try:
self.init(parsed_args)
@@ -103,6 +105,8 @@
LOG.exception("Failure during cleanup")
traceback.print_exc()
raise
+ if self.GOT_EXCEPTIONS:
+ raise Exception(self.GOT_EXCEPTIONS)
def init(self, parsed_args):
cleanup_service.init_conf()
@@ -159,7 +163,8 @@
'is_dry_run': is_dry_run,
'saved_state_json': self.json_data,
'is_preserve': is_preserve,
- 'is_save_state': is_save_state}
+ 'is_save_state': is_save_state,
+ 'got_exceptions': self.GOT_EXCEPTIONS}
for service in self.global_services:
svc = service(admin_mgr, **kwargs)
svc.run()
@@ -200,7 +205,8 @@
'saved_state_json': self.json_data,
'is_preserve': is_preserve,
'is_save_state': False,
- 'project_id': project_id}
+ 'project_id': project_id,
+ 'got_exceptions': self.GOT_EXCEPTIONS}
for service in self.project_services:
svc = service(mgr, **kwargs)
svc.run()
@@ -300,7 +306,8 @@
'is_dry_run': False,
'saved_state_json': data,
'is_preserve': False,
- 'is_save_state': True}
+ 'is_save_state': True,
+ 'got_exceptions': self.GOT_EXCEPTIONS}
for service in self.global_services:
svc = service(admin_mgr, **kwargs)
svc.run()
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 104958a..ccceb34 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -22,6 +22,7 @@
from tempest.common import utils
from tempest.common.utils import net_info
from tempest import config
+from tempest.lib import exceptions
LOG = logging.getLogger(__name__)
CONF = config.CONF
@@ -127,12 +128,23 @@
pass
def run(self):
- if self.is_dry_run:
- self.dry_run()
- elif self.is_save_state:
- self.save_state()
- else:
- self.delete()
+ try:
+ if self.is_dry_run:
+ self.dry_run()
+ elif self.is_save_state:
+ self.save_state()
+ else:
+ self.delete()
+ except exceptions.NotImplemented as exc:
+ # Many OpenStack services use extensions logic to implement the
+ # features or resources. Tempest cleanup tries to clean up the test
+ # resources without having much logic of extensions checks etc.
+ # If any of the extension is missing then, service will return
+ # NotImplemented error.
+ msg = ("Got NotImplemented error in %s, full exception: %s" %
+ (str(self.__class__), str(exc)))
+ LOG.exception(msg)
+ self.got_exceptions.append(msg)
class SnapshotService(BaseService):
diff --git a/tempest/tests/cmd/test_cleanup.py b/tempest/tests/cmd/test_cleanup.py
index b47da0b..1618df9 100644
--- a/tempest/tests/cmd/test_cleanup.py
+++ b/tempest/tests/cmd/test_cleanup.py
@@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import mock
+
from tempest.cmd import cleanup
from tempest.tests import base
@@ -24,3 +26,17 @@
test_saved_json = 'tempest/tests/cmd/test_saved_state_json.json'
# test if the file is loaded without any issues/exceptions
c._load_json(test_saved_json)
+
+ @mock.patch('tempest.cmd.cleanup.TempestCleanup.init')
+ @mock.patch('tempest.cmd.cleanup.TempestCleanup._cleanup')
+ def test_take_action_got_exception(self, mock_cleanup, mock_init):
+ c = cleanup.TempestCleanup(None, None, 'test')
+ c.GOT_EXCEPTIONS.append('exception')
+ mock_cleanup.return_value = True
+ mock_init.return_value = True
+ try:
+ c.take_action(mock.Mock())
+ except Exception as exc:
+ self.assertEqual(str(exc), '[\'exception\']')
+ return
+ assert False
diff --git a/tempest/tests/cmd/test_cleanup_services.py b/tempest/tests/cmd/test_cleanup_services.py
index 3262b1c..de0dbec 100644
--- a/tempest/tests/cmd/test_cleanup_services.py
+++ b/tempest/tests/cmd/test_cleanup_services.py
@@ -19,6 +19,7 @@
from tempest import clients
from tempest.cmd import cleanup_service
from tempest import config
+from tempest.lib import exceptions
from tempest.tests import base
from tempest.tests import fake_config
from tempest.tests.lib import fake_credentials
@@ -27,13 +28,24 @@
class TestBaseService(base.TestCase):
+ class TestException(cleanup_service.BaseService):
+ def delete(self):
+ raise exceptions.NotImplemented
+
+ def dry_run(self):
+ raise exceptions.NotImplemented
+
+ def save_state(self):
+ raise exceptions.NotImplemented
+
def test_base_service_init(self):
kwargs = {'data': {'data': 'test'},
'is_dry_run': False,
'saved_state_json': {'saved': 'data'},
'is_preserve': False,
'is_save_state': True,
- 'tenant_id': 'project_id'}
+ 'tenant_id': 'project_id',
+ 'got_exceptions': []}
base = cleanup_service.BaseService(kwargs)
self.assertEqual(base.data, kwargs['data'])
self.assertFalse(base.is_dry_run)
@@ -41,6 +53,28 @@
self.assertFalse(base.is_preserve)
self.assertTrue(base.is_save_state)
self.assertEqual(base.tenant_filter['project_id'], kwargs['tenant_id'])
+ self.assertEqual(base.got_exceptions, kwargs['got_exceptions'])
+
+ def test_not_implemented_ex(self):
+ kwargs = {'data': {'data': 'test'},
+ 'is_dry_run': False,
+ 'saved_state_json': {'saved': 'data'},
+ 'is_preserve': False,
+ 'is_save_state': False,
+ 'tenant_id': 'project_id',
+ 'got_exceptions': []}
+ base = self.TestException(kwargs)
+ # delete
+ base.run()
+ self.assertEqual(len(base.got_exceptions), 1)
+ # save_state
+ base.save_state = True
+ base.run()
+ self.assertEqual(len(base.got_exceptions), 2)
+ # dry_run
+ base.is_dry_run = True
+ base.run()
+ self.assertEqual(len(base.got_exceptions), 3)
class MockFunctionsBase(base.TestCase):