From 297d02bada2769ea013217e286f54a0cc7baed81 Mon Sep 17 00:00:00 2001 From: Boris Pavlovic Date: Thu, 3 Oct 2013 17:14:45 +0400 Subject: [PATCH] Add benchmark scenarios base class Every benchmark should be subclass of base.Scenario. This allows us to implement next things: *) Auto discovering of benchmark Scenarios *) Init & CleanUp functionality for benchmark Scenarios *) All becnhmark Scenarios have built-in os python clients blueprint test-engine-remove-pytest Change-Id: I76f70b5bf3d35c3db8bb4d6f94f179c91f6f36a9 --- rally/benchmark/base.py | 67 +++++++++++++++++++++++++++++++ rally/exceptions.py | 4 ++ tests/benchmark/test_base.py | 76 ++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 rally/benchmark/base.py create mode 100644 tests/benchmark/test_base.py diff --git a/rally/benchmark/base.py b/rally/benchmark/base.py new file mode 100644 index 0000000000..2e7e58d9aa --- /dev/null +++ b/rally/benchmark/base.py @@ -0,0 +1,67 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# 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. + +from rally import exceptions +from rally import osclients +from rally import utils + +# NOTE(boris-42): Load all modules with scenarios. This is required by +# Scenraio.get_by_name() function. So it will be able to find +# all scenarios that are written in rally.bencmark.scenarios.* +utils.import_modules_from_package("rally.benchmark.scenarios") + + +class Scenario(object): + """This is base class for any benchmark scenario. + You should create subclass of this class. And you test scnerios will + be autodiscoverd and you will be able to specify it in test config. + """ + @staticmethod + def get_by_name(name): + """Returns Scenario class by name.""" + for scenario in utils.itersubclasses(Scenario): + if name == scenario.__name__: + return scenario + raise exceptions.NoSuchScenario(name=name) + + @classmethod + def class_init(cls, cloud_endpoints): + keys = ["admin_username", "admin_password", "admin_tenant_name", + "auth_url"] + clients = osclients.Clients(*[cloud_endpoints[k] for k in keys]) + + cls.cloud_endpoints = cloud_endpoints + cls.nova = clients.get_nova_client() + cls.keystone = clients.get_keystone_client() + cls.glance = clients.get_glance_client() + cls.cinder = clients.get_cinder_client() + + @staticmethod + def init(config): + """This method will be called with test config. It purpose is to + prepare test enviorment. E.g. if you would like to test + performance of assing of FloatingIps here you will create 200k + FloatinigIps anre retun information about it to + """ + return {} + + @staticmethod + def cleanup(context): + """This method will be called with context that was returned by init, + after test scneario will be finished. And it should free all + allocated resources. + """ diff --git a/rally/exceptions.py b/rally/exceptions.py index 103ac7eb5d..e128c4bb2b 100644 --- a/rally/exceptions.py +++ b/rally/exceptions.py @@ -112,6 +112,10 @@ class NoSuchVMProvider(NotFoundException): msg_fmt = _("There is no vm provider with name `%(vm_provider_name)s`.") +class NoSuchScenario(NotFoundException): + msg_fmt = _("There is no benchmark scenario with name `%(name)s`.") + + class TaskNotFound(NotFoundException): msg_fmt = _("Task with uuid=%(uuid)s not found.") diff --git a/tests/benchmark/test_base.py b/tests/benchmark/test_base.py new file mode 100644 index 0000000000..2316f1e901 --- /dev/null +++ b/tests/benchmark/test_base.py @@ -0,0 +1,76 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# 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. + +import mock + +from rally.benchmark import base +from rally import exceptions +from rally import test + + +class ScenarioTestCase(test.NoDBTestCase): + + def test_get_by_name(self): + + class Scenario1(base.Scenario): + pass + + class Scenario2(base.Scenario): + pass + + for s in [Scenario1, Scenario2]: + self.assertEqual(s, base.Scenario.get_by_name(s.__name__)) + + def test_get_by_name_not_found(self): + self.assertRaises(exceptions.NoSuchScenario, + base.Scenario.get_by_name, "non existing scenario") + + def test_class_init(self): + + class FakeClients(object): + + def get_keystone_client(self): + return "keystone" + + def get_nova_client(self): + return "nova" + + def get_glance_client(self): + return "glance" + + def get_cinder_client(self): + return "cinder" + + with mock.patch('rally.benchmark.base.osclients') as mock_osclients: + mock_osclients.Clients = mock.MagicMock(return_value=FakeClients()) + + keys = ["admin_username", "admin_password", "admin_tenant_name", + "auth_url"] + kw = dict(zip(keys, keys)) + + base.Scenario.class_init(kw) + self.assertEqual(mock_osclients.Clients.mock_calls, + [mock.call(*keys)]) + + for k in ["keystone", "nova", "glance", "cinder"]: + self.assertEqual(getattr(base.Scenario, k), k) + + def test_init(self): + self.assertEqual({}, base.Scenario.init(None)) + + def test_cleanup(self): + base.Scenario.cleanup(None)