Add generic keystone cleanup mechanism

We should delete all created by benchmark resources:
"users", "roles", "services", "tenants" after benchmark execution.

We decide to use specific template in names.
(all names starts with "rally_k_" so we are able easy to check was
this resource created by benchmark or not).

blueprint keystone-benchmark

Change-Id: If5372138410a160c693314ebf0e728efd2682814
This commit is contained in:
Boris Pavlovic
2013-12-27 04:24:13 +04:00
parent 4dcb8c84be
commit 52f7f8b122
5 changed files with 50 additions and 2 deletions

View File

@@ -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()

View File

@@ -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)

View File

@@ -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()

View File

@@ -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)