Adding the scenarios module and the scenarios
Change-Id: Id7948b1bbf3c2a83d1d26dd6c8512bb9c8912ce8 Implements: blueprint cloudpulse-ext-handler
This commit is contained in:
parent
51aa7f5e8c
commit
623cbb217c
0
cloudpulse/scenario/__init__.py
Normal file
0
cloudpulse/scenario/__init__.py
Normal file
222
cloudpulse/scenario/base.py
Normal file
222
cloudpulse/scenario/base.py
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
# 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 cloudpulse.common import exception
|
||||||
|
from cloudpulse.common.plugin import discover
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
|
||||||
|
def scenario(admin_only=False, operator=False, context=None):
|
||||||
|
"""Add extra fields to benchmark scenarios methods.
|
||||||
|
|
||||||
|
This method is used as decorator for the methods of benchmark scenarios
|
||||||
|
and it adds following extra fields to the methods.
|
||||||
|
|
||||||
|
'is_scenario' is set to True
|
||||||
|
'admin_only' is set to True if a scenario require admin endpoints
|
||||||
|
'operator' is set to True if the scenario is an operator scenario
|
||||||
|
"""
|
||||||
|
|
||||||
|
def wrapper(func):
|
||||||
|
func.is_scenario = True
|
||||||
|
func.admin_only = admin_only
|
||||||
|
func.operator = operator
|
||||||
|
func.context = context or {}
|
||||||
|
return func
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
class Scenario(object):
|
||||||
|
"""This is base class for any benchmark scenario.
|
||||||
|
|
||||||
|
You should create subclass of this class. And your test scenarios will
|
||||||
|
be auto discoverable and you will be able to specify it in test config.
|
||||||
|
"""
|
||||||
|
def __init__(self, context=None, admin_tests=None,
|
||||||
|
tenant_tests=None, operator_tests=None):
|
||||||
|
self._admin_tests = admin_tests
|
||||||
|
self.tenant_tests = tenant_tests
|
||||||
|
self.operator_tests = operator_tests
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_by_name(name):
|
||||||
|
"""Returns Scenario class by name."""
|
||||||
|
for scenario in discover.itersubclasses(Scenario):
|
||||||
|
if name == scenario.__name__:
|
||||||
|
return scenario
|
||||||
|
raise exception.NoSuchScenario(name=name)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_scenario(cls, method_name):
|
||||||
|
"""Check whether a given method in scenario class is a scenario.
|
||||||
|
|
||||||
|
:param cls: scenario class
|
||||||
|
:param method_name: method name
|
||||||
|
|
||||||
|
:returns: True if the method is a benchmark scenario, False otherwise
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
getattr(cls, method_name)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return Scenario.meta(cls, "is_scenario", method_name, default=False)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_admin(cls, method_name):
|
||||||
|
"""Check whether a given method in scenario class is a scenario.
|
||||||
|
|
||||||
|
:param cls: scenario class
|
||||||
|
:param method_name: method name
|
||||||
|
|
||||||
|
:returns: True if the method is a benchmark scenario, False otherwise
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
getattr(cls, method_name)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return Scenario.meta(cls, "admin_only", method_name, default=False)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_operator(cls, method_name):
|
||||||
|
"""Check whether a given method in scenario class is a scenario.
|
||||||
|
|
||||||
|
:param cls: scenario class
|
||||||
|
:param method_name: method name
|
||||||
|
|
||||||
|
:returns: True if the method is a benchmark scenario, False otherwise
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
getattr(cls, method_name)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return Scenario.meta(cls, "operator", method_name, default=False)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list_operator_scenarios(scenario_cls):
|
||||||
|
"""Lists all the existing methods in the operator scenario classes.
|
||||||
|
|
||||||
|
Returns the method names in format <Class name>.<Method name>, which
|
||||||
|
is used in the test config.
|
||||||
|
|
||||||
|
:returns: List of strings
|
||||||
|
"""
|
||||||
|
scenario_classes = (list(discover.itersubclasses(scenario_cls)) +
|
||||||
|
[scenario_cls])
|
||||||
|
scenarios_list = [
|
||||||
|
["%s.%s" % (scenario.__name__, func)
|
||||||
|
for func in dir(scenario)
|
||||||
|
if Scenario.is_scenario(scenario, func)
|
||||||
|
and Scenario.is_operator(scenario, func)]
|
||||||
|
for scenario in scenario_classes
|
||||||
|
]
|
||||||
|
operator_scenarios = list(
|
||||||
|
itertools.chain.from_iterable(scenarios_list))
|
||||||
|
return operator_scenarios
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list_admin_scenarios(scenario_cls):
|
||||||
|
"""Lists all the existing methods in the operator scenario classes.
|
||||||
|
|
||||||
|
Returns the method names in format <Class name>.<Method name>, which
|
||||||
|
is used in the test config.
|
||||||
|
|
||||||
|
:returns: List of strings
|
||||||
|
"""
|
||||||
|
scenario_classes = (list(discover.itersubclasses(scenario_cls)) +
|
||||||
|
[scenario_cls])
|
||||||
|
scenarios_list = [
|
||||||
|
["%s.%s" % (scenario.__name__, func)
|
||||||
|
for func in dir(scenario)
|
||||||
|
if Scenario.is_scenario(scenario, func) and
|
||||||
|
Scenario.is_admin(scenario, func)]
|
||||||
|
for scenario in scenario_classes
|
||||||
|
]
|
||||||
|
scenarios_list_admin = list(
|
||||||
|
itertools.chain.from_iterable(scenarios_list))
|
||||||
|
return scenarios_list_admin
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list_tenant_scenarios(scenario_cls):
|
||||||
|
"""Lists all the existing methods in the operator scenario classes.
|
||||||
|
|
||||||
|
Returns the method names in format <Class name>.<Method name>, which
|
||||||
|
is used in the test config.
|
||||||
|
|
||||||
|
:returns: List of strings
|
||||||
|
"""
|
||||||
|
scenario_classes = (list(discover.itersubclasses(scenario_cls)) +
|
||||||
|
[scenario_cls])
|
||||||
|
scenarios_list = [
|
||||||
|
["%s.%s" % (scenario.__name__, func)
|
||||||
|
for func in dir(scenario)
|
||||||
|
if Scenario.is_scenario(scenario, func) and
|
||||||
|
not Scenario.is_admin(scenario, func) and
|
||||||
|
not Scenario.is_operator(scenario, func)]
|
||||||
|
for scenario in scenario_classes
|
||||||
|
]
|
||||||
|
tenant_scenarios = list(
|
||||||
|
itertools.chain.from_iterable(scenarios_list))
|
||||||
|
return tenant_scenarios
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list_all_scenarios(scenario_cls):
|
||||||
|
"""Lists all the existing methods in the operator scenario classes.
|
||||||
|
|
||||||
|
Returns the method names in format <Class name>.<Method name>, which
|
||||||
|
is used in the test config.
|
||||||
|
|
||||||
|
:returns: List of strings
|
||||||
|
"""
|
||||||
|
scenario_classes = (list(discover.itersubclasses(scenario_cls)) +
|
||||||
|
[scenario_cls])
|
||||||
|
scenarios_list = [
|
||||||
|
["%s.%s" % (scenario.__name__, func)
|
||||||
|
for func in dir(scenario) if Scenario.is_scenario(scenario, func)]
|
||||||
|
for scenario in scenario_classes
|
||||||
|
]
|
||||||
|
scenarios_list_flat = list(
|
||||||
|
itertools.chain.from_iterable(scenarios_list))
|
||||||
|
return scenarios_list_flat
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def validate(cls, name, config, admin=None, users=None, task=None):
|
||||||
|
"""Semantic check of benchmark arguments."""
|
||||||
|
if cls.meta(name, "admin_only") is True:
|
||||||
|
print("Admin Access")
|
||||||
|
if cls.meta(name, "operator") is True:
|
||||||
|
print("Operator")
|
||||||
|
|
||||||
|
def setup(self, *args, **kwargs):
|
||||||
|
"""TODO:Implement setup and teardown"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def teardown(self, *args, **kwargs):
|
||||||
|
"""TODO:Implement setup and teardown"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def meta(cls, attr_name, method_name=None, default=None):
|
||||||
|
"""Extract the named meta information out of the scenario name.
|
||||||
|
|
||||||
|
:param cls: Scenario (sub)class or string of form 'class.method'
|
||||||
|
:param attr_name: Name of method attribute holding meta information.
|
||||||
|
:param method_name: Name of method queried for meta information.
|
||||||
|
:param default: Value returned if no meta information is attached.
|
||||||
|
|
||||||
|
:returns: Meta value bound to method attribute or default.
|
||||||
|
"""
|
||||||
|
if isinstance(cls, str):
|
||||||
|
cls_name, method_name = cls.split(".", 1)
|
||||||
|
cls = Scenario.get_by_name(cls_name)
|
||||||
|
method = getattr(cls, method_name)
|
||||||
|
return getattr(method, attr_name, default)
|
0
cloudpulse/scenario/plugins/__init__.py
Normal file
0
cloudpulse/scenario/plugins/__init__.py
Normal file
0
cloudpulse/scenario/plugins/dummy/__init__.py
Normal file
0
cloudpulse/scenario/plugins/dummy/__init__.py
Normal file
32
cloudpulse/scenario/plugins/dummy/dummy_test.py
Normal file
32
cloudpulse/scenario/plugins/dummy/dummy_test.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# 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 cloudpulse.scenario import base
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
TESTS_OPTS = [
|
||||||
|
cfg.IntOpt('dummy_cloudtest',
|
||||||
|
default=0,
|
||||||
|
help='The nova endpoint and interval')
|
||||||
|
]
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
periodic_test_group = cfg.OptGroup(name='periodic_tests',
|
||||||
|
title='Periodic tests to be run')
|
||||||
|
CONF.register_opts(TESTS_OPTS, periodic_test_group)
|
||||||
|
|
||||||
|
|
||||||
|
class dummy_scenario(base.Scenario):
|
||||||
|
@base.scenario(operator=True)
|
||||||
|
def dummy_cloudtest(self, *args, **kwargs):
|
||||||
|
return (200, "success", ['dummy_result'])
|
100
cloudpulse/scenario/plugins/endpoint_tests/endpoint.py
Normal file
100
cloudpulse/scenario/plugins/endpoint_tests/endpoint.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
# 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 cloudpulse.openstack.api.cinder_api import CinderHealth
|
||||||
|
from cloudpulse.openstack.api.glance_api import GlanceHealth
|
||||||
|
from cloudpulse.openstack.api.keystone_api import KeystoneHealth
|
||||||
|
from cloudpulse.openstack.api.neutron_api import NeutronHealth
|
||||||
|
from cloudpulse.openstack.api.nova_api import NovaHealth
|
||||||
|
from cloudpulse.scenario import base
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_utils import importutils
|
||||||
|
|
||||||
|
cfg.CONF.import_opt('auth_uri', 'keystonemiddleware.auth_token',
|
||||||
|
group='keystone_authtoken')
|
||||||
|
|
||||||
|
TESTS_OPTS = [
|
||||||
|
cfg.IntOpt('nova_endpoint',
|
||||||
|
default=0,
|
||||||
|
help='The nova endpoint and interval'),
|
||||||
|
cfg.IntOpt('neutron_endpoint',
|
||||||
|
default=0,
|
||||||
|
help='The neutron endpoint and interval'),
|
||||||
|
cfg.IntOpt('keystone_endpoint',
|
||||||
|
default=0,
|
||||||
|
help='The keystone endpoint and interval'),
|
||||||
|
cfg.IntOpt('glance_endpoint',
|
||||||
|
default=0,
|
||||||
|
help='The glance endpoint and interval'),
|
||||||
|
cfg.IntOpt('cinder_endpoint',
|
||||||
|
default=0,
|
||||||
|
help='The cinder endpoint and interval')
|
||||||
|
]
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
periodic_test_group = cfg.OptGroup(name='periodic_tests',
|
||||||
|
title='Periodic tests to be run')
|
||||||
|
CONF.register_group(periodic_test_group)
|
||||||
|
CONF.register_opts(TESTS_OPTS, periodic_test_group)
|
||||||
|
|
||||||
|
|
||||||
|
class endpoint_scenario(base.Scenario):
|
||||||
|
def _get_credentials(self):
|
||||||
|
importutils.import_module('keystonemiddleware.auth_token')
|
||||||
|
creds = {}
|
||||||
|
creds['username'] = cfg.CONF.keystone_authtoken.username
|
||||||
|
creds['tenant_name'] = cfg.CONF.keystone_authtoken.project_name
|
||||||
|
creds['password'] = cfg.CONF.keystone_authtoken.password
|
||||||
|
creds['auth_url'] = cfg.CONF.keystone_authtoken.auth_uri
|
||||||
|
return creds
|
||||||
|
|
||||||
|
def _get_nova_v2_credentials(self):
|
||||||
|
importutils.import_module('keystonemiddleware.auth_token')
|
||||||
|
creds = {}
|
||||||
|
creds['username'] = cfg.CONF.keystone_authtoken.username
|
||||||
|
creds['project_id'] = cfg.CONF.keystone_authtoken.project_name
|
||||||
|
creds['api_key'] = cfg.CONF.keystone_authtoken.password
|
||||||
|
creds['auth_url'] = cfg.CONF.keystone_authtoken.auth_uri
|
||||||
|
creds['version'] = 2
|
||||||
|
return creds
|
||||||
|
|
||||||
|
@base.scenario(admin_only=False, operator=False)
|
||||||
|
def nova_endpoint(self, *args, **kwargs):
|
||||||
|
creds = self._get_nova_v2_credentials()
|
||||||
|
nova = NovaHealth(creds)
|
||||||
|
return nova.nova_service_list()
|
||||||
|
|
||||||
|
@base.scenario(admin_only=False, operator=False)
|
||||||
|
def neutron_endpoint(self, *args, **kwargs):
|
||||||
|
creds = self._get_credentials()
|
||||||
|
neutron = NeutronHealth(creds)
|
||||||
|
return neutron.neutron_agent_list()
|
||||||
|
|
||||||
|
@base.scenario(admin_only=False, operator=False)
|
||||||
|
def keystone_endpoint(self, *args, **kwargs):
|
||||||
|
creds = self._get_credentials()
|
||||||
|
keystone = KeystoneHealth(creds)
|
||||||
|
return keystone.keystone_service_list()
|
||||||
|
|
||||||
|
@base.scenario(admin_only=False, operator=False)
|
||||||
|
def glance_endpoint(self, *args, **kwargs):
|
||||||
|
creds = self._get_credentials()
|
||||||
|
keystone = KeystoneHealth(creds)
|
||||||
|
glance = GlanceHealth(keystone)
|
||||||
|
return glance.glance_image_list()
|
||||||
|
|
||||||
|
@base.scenario(admin_only=False, operator=False)
|
||||||
|
def cinder_endpoint(self, *args, **kwargs):
|
||||||
|
creds = self._get_nova_v2_credentials()
|
||||||
|
cinder = CinderHealth(creds)
|
||||||
|
return cinder.cinder_list()
|
Loading…
x
Reference in New Issue
Block a user