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
This commit is contained in:
Boris Pavlovic 2013-10-03 17:14:45 +04:00
parent d3473afc19
commit 297d02bada
3 changed files with 147 additions and 0 deletions

67
rally/benchmark/base.py Normal file
View File

@ -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.
"""

View File

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

View File

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