diff --git a/rally/plugins/openstack/context/cleanup/__init__.py b/rally/plugins/openstack/context/cleanup/__init__.py index a38ef87f..e69de29b 100644 --- a/rally/plugins/openstack/context/cleanup/__init__.py +++ b/rally/plugins/openstack/context/cleanup/__init__.py @@ -1,99 +0,0 @@ -# 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 - -from rally.common.i18n import _ -from rally.common import logging -from rally import consts -from rally import exceptions -from rally.plugins.openstack.cleanup import manager -from rally.task import context - - -LOG = logging.getLogger(__name__) - - -class NoSuchCleanupResources(exceptions.RallyException): - msg_fmt = _("Missing cleanup resource managers: %(message)s") - - -class CleanupMixin(object): - - CONFIG_SCHEMA = { - "type": "array", - "$schema": consts.JSON_SCHEMA, - "items": { - "type": "string", - }, - "additionalProperties": False - } - - def setup(self): - pass - - -# NOTE(amaretskiy): Set order to run this just before UserCleanup -@context.configure(name="admin_cleanup", order=(sys.maxsize - 1), hidden=True) -class AdminCleanup(CleanupMixin, context.Context): - """Context class for admin resources cleanup.""" - - @classmethod - def validate(cls, config, non_hidden=False): - super(AdminCleanup, cls).validate(config, non_hidden) - - missing = set(config) - missing -= manager.list_resource_names(admin_required=True) - missing = ", ".join(missing) - if missing: - LOG.info(_("Couldn't find cleanup resource managers: %s") - % missing) - raise NoSuchCleanupResources(missing) - - @logging.log_task_wrapper(LOG.info, _("admin resources cleanup")) - def cleanup(self): - manager.cleanup( - names=self.config, - admin_required=True, - admin=self.context["admin"], - users=self.context.get("users", []), - api_versions=self.context["config"].get("api_versions")) - - -# NOTE(amaretskiy): Set maximum order to run this last -@context.configure(name="cleanup", order=sys.maxsize, hidden=True) -class UserCleanup(CleanupMixin, context.Context): - """Context class for user resources cleanup.""" - - @classmethod - def validate(cls, config, non_hidden=False): - super(UserCleanup, cls).validate(config, non_hidden) - - missing = set(config) - missing -= manager.list_resource_names(admin_required=False) - missing = ", ".join(missing) - if missing: - LOG.info(_("Couldn't find cleanup resource managers: %s") - % missing) - raise NoSuchCleanupResources(missing) - - @logging.log_task_wrapper(LOG.info, _("user resources cleanup")) - def cleanup(self): - manager.cleanup( - names=self.config, - admin_required=False, - users=self.context.get("users", []), - api_versions=self.context["config"].get("api_versions") - ) diff --git a/rally/plugins/openstack/context/cleanup/admin.py b/rally/plugins/openstack/context/cleanup/admin.py new file mode 100644 index 00000000..b318e546 --- /dev/null +++ b/rally/plugins/openstack/context/cleanup/admin.py @@ -0,0 +1,52 @@ +# 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 + +from rally.common.i18n import _ +from rally.common import logging +from rally.plugins.openstack.cleanup import manager +from rally.plugins.openstack.context.cleanup import base +from rally.task import context + + +LOG = logging.getLogger(__name__) + + +# NOTE(amaretskiy): Set order to run this just before UserCleanup +@context.configure(name="admin_cleanup", order=(sys.maxsize - 1), hidden=True) +class AdminCleanup(base.CleanupMixin, context.Context): + """Context class for admin resources cleanup.""" + + @classmethod + def validate(cls, config, non_hidden=False): + super(AdminCleanup, cls).validate(config, non_hidden) + + missing = set(config) + missing -= manager.list_resource_names(admin_required=True) + missing = ", ".join(missing) + if missing: + LOG.info(_("Couldn't find cleanup resource managers: %s") + % missing) + raise base.NoSuchCleanupResources(missing) + + @logging.log_task_wrapper(LOG.info, _("admin resources cleanup")) + def cleanup(self): + manager.cleanup( + names=self.config, + admin_required=True, + admin=self.context["admin"], + users=self.context.get("users", []), + api_versions=self.context["config"].get("api_versions")) diff --git a/rally/plugins/openstack/context/cleanup/base.py b/rally/plugins/openstack/context/cleanup/base.py index d269e413..c092f1a0 100644 --- a/rally/plugins/openstack/context/cleanup/base.py +++ b/rally/plugins/openstack/context/cleanup/base.py @@ -1,4 +1,4 @@ -# +# Copyright 2014: Mirantis Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -13,15 +13,29 @@ # License for the specific language governing permissions and limitations # under the License. -# NOTE(stpierre): This module is left for backward compatibility. +from rally.common.i18n import _ +from rally.common import logging +from rally import consts +from rally import exceptions -import sys -import warnings -from rally.plugins.openstack.cleanup import base +LOG = logging.getLogger(__name__) -warnings.warn("Module rally.plugins.openstack.context.cleanup.base has been " - "moved to rally.plugins.openstack.cleanup.base, and will be " - "removed at some point in the future.") -sys.modules["rally.plugins.openstack.context.cleanup.base"] = base +class NoSuchCleanupResources(exceptions.RallyException): + msg_fmt = _("Missing cleanup resource managers: %(message)s") + + +class CleanupMixin(object): + + CONFIG_SCHEMA = { + "type": "array", + "$schema": consts.JSON_SCHEMA, + "items": { + "type": "string", + }, + "additionalProperties": False + } + + def setup(self): + pass diff --git a/rally/plugins/openstack/context/cleanup/user.py b/rally/plugins/openstack/context/cleanup/user.py new file mode 100644 index 00000000..e8197adc --- /dev/null +++ b/rally/plugins/openstack/context/cleanup/user.py @@ -0,0 +1,52 @@ +# 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 + +from rally.common.i18n import _ +from rally.common import logging +from rally.plugins.openstack.cleanup import manager +from rally.plugins.openstack.context.cleanup import base +from rally.task import context + + +LOG = logging.getLogger(__name__) + + +# NOTE(amaretskiy): Set maximum order to run this last +@context.configure(name="cleanup", order=sys.maxsize, hidden=True) +class UserCleanup(base.CleanupMixin, context.Context): + """Context class for user resources cleanup.""" + + @classmethod + def validate(cls, config, non_hidden=False): + super(UserCleanup, cls).validate(config, non_hidden) + + missing = set(config) + missing -= manager.list_resource_names(admin_required=False) + missing = ", ".join(missing) + if missing: + LOG.info(_("Couldn't find cleanup resource managers: %s") + % missing) + raise base.NoSuchCleanupResources(missing) + + @logging.log_task_wrapper(LOG.info, _("user resources cleanup")) + def cleanup(self): + manager.cleanup( + names=self.config, + admin_required=False, + users=self.context.get("users", []), + api_versions=self.context["config"].get("api_versions") + ) diff --git a/tests/unit/plugins/openstack/context/cleanup/__init__.py b/tests/unit/plugins/openstack/context/cleanup/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/plugins/openstack/context/cleanup/test_admin.py b/tests/unit/plugins/openstack/context/cleanup/test_admin.py new file mode 100644 index 00000000..35a2be97 --- /dev/null +++ b/tests/unit/plugins/openstack/context/cleanup/test_admin.py @@ -0,0 +1,121 @@ +# 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 jsonschema +import mock + +from rally.plugins.openstack.context.cleanup import admin +from rally.plugins.openstack.context.cleanup import base +from tests.unit import test + + +BASE = "rally.plugins.openstack.context.cleanup.admin" + + +class AdminCleanupTestCase(test.TestCase): + + @mock.patch("%s.manager" % BASE) + def test_validate(self, mock_manager): + mock_manager.list_resource_names.return_value = set(["a", "b", "c"]) + admin.AdminCleanup.validate(["a"]) + mock_manager.list_resource_names.assert_called_once_with( + admin_required=True) + + @mock.patch("%s.manager" % BASE) + def test_validate_no_such_cleanup(self, mock_manager): + mock_manager.list_resource_names.return_value = set(["a", "b", "c"]) + self.assertRaises(base.NoSuchCleanupResources, + admin.AdminCleanup.validate, ["a", "d"]) + mock_manager.list_resource_names.assert_called_once_with( + admin_required=True) + + def test_validate_invalid_config(self): + self.assertRaises(jsonschema.ValidationError, + admin.AdminCleanup.validate, {}) + + @mock.patch("%s.manager.find_resource_managers" % BASE, + return_value=[mock.MagicMock(), mock.MagicMock()]) + @mock.patch("%s.manager.SeekAndDestroy" % BASE) + def test_cleanup(self, mock_seek_and_destroy, mock_find_resource_managers): + + ctx = { + "config": {"admin_cleanup": ["a", "b"]}, + "admin": mock.MagicMock(), + "users": mock.MagicMock(), + "task": mock.MagicMock() + } + + admin_cleanup = admin.AdminCleanup(ctx) + admin_cleanup.setup() + admin_cleanup.cleanup() + + mock_find_resource_managers.assert_called_once_with(["a", "b"], True) + mock_seek_and_destroy.assert_has_calls([ + mock.call( + mock_find_resource_managers.return_value[0], + ctx["admin"], + ctx["users"], + None), + mock.call().exterminate(), + mock.call( + mock_find_resource_managers.return_value[1], + ctx["admin"], + ctx["users"], + None), + mock.call().exterminate() + ]) + + @mock.patch("%s.manager.find_resource_managers" % BASE, + return_value=[mock.MagicMock(), mock.MagicMock()]) + @mock.patch("%s.manager.SeekAndDestroy" % BASE) + def test_cleanup_admin_with_api_versions( + self, + mock_seek_and_destroy, + mock_find_resource_managers): + + ctx = { + "config": + {"admin_cleanup": ["a", "b"], + "api_versions": + {"cinder": + {"version": "1", + "service_type": "volume" + } + } + }, + "admin": mock.MagicMock(), + "users": mock.MagicMock(), + "task": mock.MagicMock() + } + + admin_cleanup = admin.AdminCleanup(ctx) + admin_cleanup.setup() + admin_cleanup.cleanup() + + mock_find_resource_managers.assert_called_once_with(["a", "b"], True) + mock_seek_and_destroy.assert_has_calls([ + mock.call( + mock_find_resource_managers.return_value[0], + ctx["admin"], + ctx["users"], + ctx["config"]["api_versions"]), + mock.call().exterminate(), + mock.call( + mock_find_resource_managers.return_value[1], + ctx["admin"], + ctx["users"], + ctx["config"]["api_versions"]), + mock.call().exterminate() + ]) diff --git a/tests/unit/plugins/openstack/context/cleanup/test_user.py b/tests/unit/plugins/openstack/context/cleanup/test_user.py new file mode 100644 index 00000000..3475e3cf --- /dev/null +++ b/tests/unit/plugins/openstack/context/cleanup/test_user.py @@ -0,0 +1,117 @@ +# 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 jsonschema +import mock + +from rally.plugins.openstack.context.cleanup import base +from rally.plugins.openstack.context.cleanup import user +from tests.unit import test + + +BASE = "rally.plugins.openstack.context.cleanup.user" + + +class UserCleanupTestCase(test.TestCase): + + @mock.patch("%s.manager" % BASE) + def test_validate(self, mock_manager): + mock_manager.list_resource_names.return_value = set(["a", "b", "c"]) + user.UserCleanup.validate(["a"]) + mock_manager.list_resource_names.assert_called_once_with( + admin_required=False) + + @mock.patch("%s.manager" % BASE) + def test_validate_no_such_cleanup(self, mock_manager): + mock_manager.list_resource_names.return_value = set(["a", "b", "c"]) + self.assertRaises(base.NoSuchCleanupResources, + user.UserCleanup.validate, ["a", "b", "d"]) + mock_manager.list_resource_names.assert_called_once_with( + admin_required=False) + + def test_validate_invalid_config(self): + self.assertRaises(jsonschema.ValidationError, + user.UserCleanup.validate, {}) + + @mock.patch("%s.manager.find_resource_managers" % BASE, + return_value=[mock.MagicMock(), mock.MagicMock()]) + @mock.patch("%s.manager.SeekAndDestroy" % BASE) + def test_cleanup(self, mock_seek_and_destroy, mock_find_resource_managers): + + ctx = { + "config": {"cleanup": ["a", "b"]}, + "users": mock.MagicMock(), + "task": mock.MagicMock() + } + + admin_cleanup = user.UserCleanup(ctx) + admin_cleanup.setup() + admin_cleanup.cleanup() + + mock_find_resource_managers.assert_called_once_with(["a", "b"], False) + + mock_seek_and_destroy.assert_has_calls([ + mock.call( + mock_find_resource_managers.return_value[0], + None, ctx["users"], None), + mock.call().exterminate(), + mock.call( + mock_find_resource_managers.return_value[1], + None, ctx["users"], None), + mock.call().exterminate() + ]) + + @mock.patch("%s.manager.find_resource_managers" % BASE, + return_value=[mock.MagicMock(), mock.MagicMock()]) + @mock.patch("%s.manager.SeekAndDestroy" % BASE) + def test_cleanup_user_with_api_versions( + self, + mock_seek_and_destroy, + mock_find_resource_managers): + + ctx = { + "config": + {"admin_cleanup": ["a", "b"], + "api_versions": + {"cinder": + {"version": "1", + "service_type": "volume" + } + } + }, + "admin": mock.MagicMock(), + "users": mock.MagicMock(), + "task": mock.MagicMock() + } + + user_cleanup = user.UserCleanup(ctx) + user_cleanup.setup() + user_cleanup.cleanup() + + mock_find_resource_managers.assert_called_once_with({}, False) + mock_seek_and_destroy.assert_has_calls([ + mock.call( + mock_find_resource_managers.return_value[0], + None, + ctx["users"], + ctx["config"]["api_versions"]), + mock.call().exterminate(), + mock.call( + mock_find_resource_managers.return_value[1], + None, + ctx["users"], + ctx["config"]["api_versions"]), + mock.call().exterminate() + ])