diff --git a/rally/benchmark/runner.py b/rally/benchmark/runner.py index 255af915fa..ece5cc4774 100644 --- a/rally/benchmark/runner.py +++ b/rally/benchmark/runner.py @@ -17,6 +17,7 @@ import collections import multiprocessing from multiprocessing import pool as multiprocessing_pool import random +import sys import time import uuid @@ -116,6 +117,11 @@ class ScenarioRunner(object): def _delete_glance_resources(cls, glance, project_uuid): utils.delete_images(glance, project_uuid) + def _delete_keystone_resources(self): + kclient = __admin_clients__["keystone"] + for resource in ["users", "tenants", "services", "roles"]: + utils.delete_keystone_resources(kclient, resource) + @classmethod def _cleanup_with_clients(cls, indexes): for index in indexes: @@ -137,6 +143,14 @@ class ScenarioRunner(object): for client_indicies in chunked_indexes: pool.apply_async(utils.async_cleanup, args=(ScenarioRunner, client_indicies,)) + try: + self._delete_keystone_resources() + except Exception as e: + LOG.debug(_("Not all resources were cleaned."), + exc_info=sys.exc_info()) + LOG.warning(_('Unable to fully cleanup keystone service: %s') % + (e.message)) + pool.close() pool.join() diff --git a/rally/benchmark/scenarios/keystone/__init__.py b/rally/benchmark/scenarios/keystone/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/rally/benchmark/scenarios/keystone/utils.py b/rally/benchmark/scenarios/keystone/utils.py new file mode 100644 index 0000000000..89cb8dd781 --- /dev/null +++ b/rally/benchmark/scenarios/keystone/utils.py @@ -0,0 +1,21 @@ +# Copyright 2013: Mirantis Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +TEMP_TEMPLATE = "rally_k_" + + +def is_temporary(resource): + return resource.name.startswith(TEMP_TEMPLATE) diff --git a/rally/benchmark/utils.py b/rally/benchmark/utils.py index 3da5c406d2..c79427246d 100644 --- a/rally/benchmark/utils.py +++ b/rally/benchmark/utils.py @@ -17,6 +17,7 @@ import traceback from novaclient import exceptions as nova_exceptions +from rally.benchmark.scenarios.keystone import utils as kutils from rally import exceptions as rally_exceptions from rally import osclients from rally import utils @@ -239,3 +240,9 @@ def delete_volume_backups(cinder): for backup in cinder.backups.list(): backup.delete() _wait_for_empty_list(cinder.backups, timeout=240) + + +def delete_keystone_resources(keystone, resource_name): + for resource in getattr(keystone, resource_name).list(): + if kutils.is_temporary(resource): + resource.delete() diff --git a/tests/benchmark/test_runner.py b/tests/benchmark/test_runner.py index b5a55a1f0d..fdba56b15a 100644 --- a/tests/benchmark/test_runner.py +++ b/tests/benchmark/test_runner.py @@ -361,9 +361,10 @@ class ScenarioTestCase(test.TestCase): @mock.patch("rally.benchmark.utils.create_openstack_clients") @mock.patch("rally.benchmark.runner.base") @mock.patch("rally.benchmark.utils.osclients") + @mock.patch("rally.benchmark.utils.delete_keystone_resources") @mock.patch("multiprocessing.Pool") - def test_generic_cleanup(self, mock_pool, mock_osclients, - mock_base, mock_clients): + def test_generic_cleanup(self, mock_pool, mock_del_keystone_res, + mock_osclients, mock_base, mock_clients): FakeScenario = mock.MagicMock() FakeScenario.init = mock.MagicMock(return_value={}) @@ -434,3 +435,8 @@ class ScenarioTestCase(test.TestCase): for image in nova.images.list(): self.assertEqual("DELETED", image.status, "image not purged: %s" % (image)) + + expected = [mock.call(clients[0]["keystone"], resource) for resource in + ["users", "tenants", "services", "roles"]] + + self.assertEqual(mock_del_keystone_res.mock_calls, expected)