Skip to content

Commit

Permalink
Split user and admin cleanup to 2 separate classes
Browse files Browse the repository at this point in the history
Partially implements: blueprint benchmark-context-cleanup-refactor
Change-Id: I3ba0deeb5a2793b8c45f6160fe0eda22250a1ece
  • Loading branch information
Aswad Rangnekar authored and Sergey Skripnick committed Aug 8, 2014
1 parent b1ceff6 commit 2fb4ba4
Show file tree
Hide file tree
Showing 8 changed files with 269 additions and 165 deletions.
78 changes: 78 additions & 0 deletions rally/benchmark/context/cleanup/admin_cleanup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Copyright 2014: 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.

import sys

import six

from rally.benchmark.context import base
from rally.benchmark.context.cleanup import utils
from rally.openstack.common.gettextutils import _
from rally.openstack.common import log as logging
from rally import osclients
from rally import utils as rutils


LOG = logging.getLogger(__name__)


class AdminCleanup(base.Context):
"""Context class for admin resource cleanup."""

__ctx_name__ = "admin_cleanup"
__ctx_order__ = 200
__ctx_hidden__ = True

CONFIG_SCHEMA = {
"type": "array",
"$schema": rutils.JSON_SCHEMA,
"items": {
"type": "string",
"enum": ["keystone", "quotas"]
},
"uniqueItems": True
}

def __init__(self, context):
super(AdminCleanup, self).__init__(context)
self.endpoint = None

def _cleanup_resources(self):
client = osclients.Clients(self.endpoint)

cleanup_methods = {
"keystone": (utils.delete_keystone_resources, client.keystone()),
"quotas": (utils.delete_admin_quotas, client,
self.context.get("tenants", [])),
}

for service_name in self.config:
cleanup_method = cleanup_methods[service_name]
method, client = cleanup_method[:2]
try:
method(client, *cleanup_method[2:])
except Exception as e:
LOG.debug("Not all admin resources were cleaned.",
exc_info=sys.exc_info())
LOG.warning(_('Unable to fully cleanup the cloud: %s') %
(six.text_type(e)))

@rutils.log_task_wrapper(LOG.info, _("Enter context: `admin cleanup`"))
def setup(self):
self.endpoint = self.context["admin"]["endpoint"]

@rutils.log_task_wrapper(LOG.info, _("Exit context: `admin cleanup`"))
def cleanup(self):
self._cleanup_resources()
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.

import functools
import sys

import six
Expand All @@ -29,11 +28,11 @@
LOG = logging.getLogger(__name__)


class ResourceCleaner(base.Context):
"""Context class for resource cleanup (both admin and non-admin)."""
class UserCleanup(base.Context):
"""Context class for user resource cleanup."""

__ctx_name__ = "cleanup"
__ctx_order__ = 200
__ctx_order__ = 201
__ctx_hidden__ = True

CONFIG_SCHEMA = {
Expand All @@ -42,29 +41,24 @@ class ResourceCleaner(base.Context):
"items": {
"type": "string",
"enum": ["nova", "glance", "cinder",
"quotas", "neutron", "ceilometer", "heat", "sahara"]
"neutron", "ceilometer", "heat", "sahara"]
},
"uniqueItems": True
}

def __init__(self, context):
super(ResourceCleaner, self).__init__(context)
self.admin = []
self.users = []
super(UserCleanup, self).__init__(context)
self.users_endpoints = []

@rutils.log_task_wrapper(LOG.info, _("Cleanup users resources."))
def _cleanup_users_resources(self):
for user in self.users:
def _cleanup_resources(self):
for user in self.users_endpoints:
clients = osclients.Clients(user)
admin_clients = functools.partial(osclients.Clients, self.admin)
tenant_id = clients.keystone().tenant_id
cleanup_methods = {
"nova": (utils.delete_nova_resources, clients.nova),
"glance": (utils.delete_glance_resources, clients.glance,
tenant_id),
"cinder": (utils.delete_cinder_resources, clients.cinder),
"quotas": (utils.delete_quotas, admin_clients,
tenant_id),
"neutron": (utils.delete_neutron_resources, clients.neutron,
tenant_id),
"ceilometer": (utils.delete_ceilometer_resources,
Expand All @@ -74,39 +68,23 @@ def _cleanup_users_resources(self):
}

for service_name in self.config:
cleanup_method = cleanup_methods[service_name]
method = cleanup_method[0]
client = cleanup_method[1]()
try:
service = cleanup_methods[service_name]
method = service[0]
client = service[1]()
args = service[2:]
method(client, *args)
method(client, *cleanup_method[2:])
except Exception as e:
LOG.debug("Not all resources were cleaned.",
LOG.debug("Not all user resources were cleaned.",
exc_info=sys.exc_info())
LOG.warning(_('Unable to fully cleanup the cloud: %s') %
(six.text_type(e)))

@rutils.log_task_wrapper(LOG.info, _("Cleanup admin resources."))
def _cleanup_admin_resources(self):
try:
admin = osclients.Clients(self.admin)
utils.delete_keystone_resources(admin.keystone())
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') %
(six.text_type(e)))

@rutils.log_task_wrapper(LOG.info, _("Enter context: `cleanup`"))
def setup(self):
if "admin" in self.context and self.context["admin"]:
self.admin = self.context["admin"]["endpoint"]
if "users" in self.context and self.context["users"]:
self.users = [u["endpoint"] for u in self.context["users"]]
self.users_endpoints = [u["endpoint"]
for u in self.context.get("users", [])]

@rutils.log_task_wrapper(LOG.info, _("Exit context: `cleanup`"))
def cleanup(self):
if self.users and self.config:
self._cleanup_users_resources()
if self.admin:
self._cleanup_admin_resources()
if self.users_endpoints and self.config:
self._cleanup_resources()
5 changes: 5 additions & 0 deletions rally/benchmark/context/cleanup/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ def delete_heat_resources(heat):
delete_stacks(heat)


def delete_admin_quotas(client, tenants):
for tenant in tenants:
delete_quotas(client, tenant["id"])


def delete_keystone_resources(keystone):
keystone = keystone_wrapper.wrap(keystone)
for resource in ["user", "project", "service", "role"]:
Expand Down
18 changes: 12 additions & 6 deletions rally/benchmark/scenarios/keystone/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,39 @@

class KeystoneBasic(kutils.KeystoneScenario):

@scenario_base.scenario(admin_only=True, context={"cleanup": []})
@scenario_base.scenario(admin_only=True,
context={"admin_cleanup": ["keystone"]})
def create_user(self, name_length=10, **kwargs):
self._user_create(name_length=name_length, **kwargs)

@scenario_base.scenario(admin_only=True, context={"cleanup": []})
@scenario_base.scenario(admin_only=True,
context={"admin_cleanup": ["keystone"]})
def create_delete_user(self, name_length=10, **kwargs):
user = self._user_create(name_length=name_length, **kwargs)
self._resource_delete(user)

@scenario_base.scenario(admin_only=True, context={"cleanup": []})
@scenario_base.scenario(admin_only=True,
context={"admin_cleanup": ["keystone"]})
def create_tenant(self, name_length=10, **kwargs):
self._tenant_create(name_length=name_length, **kwargs)

@scenario_base.scenario(admin_only=True, context={"cleanup": []})
@scenario_base.scenario(admin_only=True,
context={"admin_cleanup": ["keystone"]})
@validation.add(validation.required_parameters(['users_per_tenant']))
def create_tenant_with_users(self, users_per_tenant, name_length=10,
**kwargs):
tenant = self._tenant_create(name_length=name_length, **kwargs)
self._users_create(tenant, users_per_tenant=users_per_tenant,
name_length=name_length)

@scenario_base.scenario(admin_only=True, context={"cleanup": []})
@scenario_base.scenario(admin_only=True,
context={"admin_cleanup": ["keystone"]})
def create_and_list_users(self, name_length=10, **kwargs):
self._user_create(name_length=name_length, **kwargs)
self._list_users()

@scenario_base.scenario(admin_only=True, context={"cleanup": []})
@scenario_base.scenario(admin_only=True,
context={"admin_cleanup": ["keystone"]})
def create_and_list_tenants(self, name_length=10, **kwargs):
self._tenant_create(name_length=name_length, **kwargs)
self._list_tenants()
9 changes: 6 additions & 3 deletions rally/benchmark/scenarios/quotas/quotas.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@

class Quotas(utils.QuotasScenario):

@scenario_base.scenario(admin_only=True, context={"cleanup": ["quotas"]})
@scenario_base.scenario(admin_only=True,
context={"admin_cleanup": ["quotas"]})
def nova_update(self, max_quota=1024):
"""Tests updating quotas for nova.
Expand All @@ -28,7 +29,8 @@ def nova_update(self, max_quota=1024):
tenant_id = self.context()["user"]["tenant_id"]
self._update_quotas('nova', tenant_id, max_quota)

@scenario_base.scenario(admin_only=True, context={"cleanup": ["quotas"]})
@scenario_base.scenario(admin_only=True,
context={"admin_cleanup": ["quotas"]})
def nova_update_and_delete(self, max_quota=1024):
"""Tests updating and deleting quotas for nova.
Expand All @@ -39,7 +41,8 @@ def nova_update_and_delete(self, max_quota=1024):
self._update_quotas('nova', tenant_id, max_quota)
self._delete_quotas('nova', tenant_id)

@scenario_base.scenario(admin_only=True, context={"cleanup": ["quotas"]})
@scenario_base.scenario(admin_only=True,
context={"admin_cleanup": ["quotas"]})
def cinder_update(self, max_quota=1024):
"""Tests updating quotas for cinder.
Expand Down
59 changes: 59 additions & 0 deletions tests/benchmark/context/cleanup/test_admin_cleanup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Copyright 2014: 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.

import mock

from rally.benchmark.context.cleanup import admin_cleanup
from tests import fakes
from tests import test


BASE = "rally.benchmark.context.cleanup.admin_cleanup"


class AdminCleanupTestCase(test.TestCase):

def test_with_statement(self):
fake_admin_ctx = fakes.FakeUserContext({}).context
fake_admin_ctx["config"] = {"admin_cleanup": ["keystone"]}
admin_cleaner = admin_cleanup.AdminCleanup(fake_admin_ctx)
admin_cleaner.setup()

admin_cleaner._cleanup_resources = mock.MagicMock()

with admin_cleaner as cleaner:
self.assertEqual(admin_cleaner, cleaner)

admin_cleaner._cleanup_resources.assert_called_once_with()

@mock.patch("%s.osclients.Clients" % BASE)
@mock.patch("%s.utils.delete_keystone_resources" % BASE)
def test_cleaner_admin(self, mock_del_keystone, mock_clients):
context = {
"task": mock.MagicMock(),
"config": {"admin_cleanup": ["keystone"]},
"admin": {"endpoint": mock.MagicMock()},
}
res_cleaner = admin_cleanup.AdminCleanup(context)

fake_keystone = mock.MagicMock()
mock_clients.return_value.keystone.return_value = fake_keystone

with res_cleaner:
res_cleaner.setup()

mock_clients.assert_called_once_with(context["admin"]["endpoint"])
mock_clients.return_value.keystone.assert_called_with()
mock_del_keystone.assert_called_once_with(fake_keystone)
Loading

0 comments on commit 2fb4ba4

Please sign in to comment.