Refactoring of system_test classes

Some design of system_test packages:
    - move actions to separate package
    - move core fuctionality to core package

Change-Id: I7b12380a687c9cccbd44d79819f842b1b2470cd5
Implemets blueprint template-based-testcases
This commit is contained in:
Dmitry Tyzhnenko 2016-02-19 17:06:20 +02:00 committed by Dmitry Tyzhnenko
parent ba77741899
commit 82b392284a
31 changed files with 934 additions and 672 deletions

View File

@ -3,17 +3,73 @@
System tests
************
Core
====
Repository
----------
.. automodule:: system_test.core.repository
:members:
Discover
--------
.. automodule:: system_test.core.discover
:members:
Decorators
----------
.. automodule:: system_test.core.decorators
:members:
Factory
-------
.. automodule:: system_test.core.factory
:members:
Config
------
.. automodule:: system_test.core.config
:members:
Actions
=======
Base actions
------------
.. automodule:: system_test.actions.base
:members:
Fuelmaster actions
------------------
.. automodule:: system_test.actions.fuelmaster_actions
:members:
OSTF actions
------------
.. automodule:: system_test.actions.ostf_actions
:members:
Plugins actions
---------------
.. automodule:: system_test.actions.plugins_actions
:members:
Strength actions
----------------
.. automodule:: system_test.actions.strength_actions
:members:
VCenter actions
---------------
.. automodule:: system_test.actions.vcenter_actions
:members:
General tests
=============
Actions Base
------------
.. automodule:: system_test.tests.actions_base
:members:
Base actions factory
--------------------
.. automodule:: system_test.tests.base_actions_factory
ActionTest
----------
.. automodule:: system_test.tests.base
:members:
Case deploy Environment
@ -56,17 +112,7 @@ Destroy controllers
Fill root and check pacemaker
-----------------------------
.. automodule:: system_test.tests.strength.filling_root
:members:
OSTF base actions
-----------------
.. automodule:: system_test.tests.ostf_base_actions
:members:
Strength Base
-------------
.. automodule:: system_test.tests.strength.strength_base
.. automodule:: system_test.tests.strength.test_filling_root
:members:
Plugin tests
@ -107,8 +153,3 @@ Decorators
----------
.. automodule:: system_test.helpers.decorators
:members:
Utils
-----
.. automodule:: system_test.helpers.utils
:members:

View File

@ -13,11 +13,12 @@ from system_test import get_groups
from system_test import define_custom_groups
from system_test import discover_import_tests
from system_test import tests_directory
from system_test import collect_yamls
from system_test import get_path_to_config
from system_test import get_list_confignames
from system_test import get_basepath
from system_test.helpers.utils import collect_yamls
from system_test.helpers.utils import get_path_to_config
from system_test.helpers.utils import get_list_confignames
from system_test.helpers.utils import get_basepath
from system_test.core.repository import split_group_config
basedir = get_basepath()
@ -27,7 +28,8 @@ def print_explain(names):
if not isinstance(names, list):
names = [names]
out = []
for name in names:
for name in [split_group_config(i)[0] if split_group_config(i) else i
for i in names]:
for i in groups_nums[name]:
if hasattr(i, 'home'):
out.append((i.home._proboscis_entry_.parent.home, i.home))
@ -126,7 +128,8 @@ def run(**kwargs):
else:
register_system_test_cases(groups=[g])
groups_to_run.append(g)
if not set(groups_to_run) < set(get_groups()):
if not set([split_group_config(i)[0] if split_group_config(i) else i
for i in groups_to_run]) < set(get_groups()):
sys.exit('There are no cases mapped to current group, '
'please be sure that you put right test group name.')
if explain:

View File

@ -11,192 +11,43 @@
# 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 re
from fuelweb_test import logger
import proboscis.core
from proboscis import register
from proboscis import factory
from system_test.core.repository import Repository
from system_test.core.config import define_custom_groups
from system_test.core.config import tests_directory
from system_test.core.factory import ActionsFactory
from system_test.core.decorators import testcase
from system_test.core.decorators import deferred_decorator
from system_test.core.decorators import action
from system_test.core.decorators import nested_action
from system_test.core.discover import discover_import_tests
from system_test.helpers.utils import get_configs
from system_test.helpers.decorators import testcase
from system_test.core.discover import get_configs
from system_test.core.discover import collect_yamls
from system_test.core.discover import get_path_to_config
from system_test.core.discover import get_list_confignames
from system_test.core.discover import get_basepath
from system_test.core.repository import Repository
from system_test.core.repository import register_system_test_cases
from system_test.core.repository import get_groups
from proboscis.decorators import DEFAULT_REGISTRY
from system_test.tests import base_actions_factory
from system_test.helpers.utils import config_filter
tests_directory = [
'fuelweb_test/tests',
'system_test/tests',
'gates_tests'
]
__all__ = [
Repository,
ActionsFactory,
discover_import_tests,
register_system_test_cases,
get_groups,
testcase,
deferred_decorator,
action,
nested_action,
get_configs,
logger]
def cached_add_group(yamls):
def add(group, systest_group, config_name,
validate_config=True):
"""Add user friendly group
:type group_name: str
:type systest_group: str
:type config_name: str
"""
# from proboscis.decorators import DEFAULT_REGISTRY
if validate_config and config_name not in yamls:
raise NameError("Config {} not found".format(config_name))
register_system_test_cases(groups=[systest_group],
configs=[config_name])
register(groups=[group],
depends_on_groups=[
"{systest_group}({config_name})".format(
systest_group=systest_group,
config_name=config_name)])
return add
def define_custom_groups():
"""Map user friendly group name to system test groups
groups - contained user friendly alias
depends - contained groups which should be runned
"""
add_group = cached_add_group(get_configs())
add_group(group="system_test.ceph_ha",
systest_group="system_test.deploy_and_check_radosgw",
config_name="ceph_all_on_neutron_vlan")
add_group(group="filling_root",
systest_group="system_test.failover.filling_root",
config_name="ceph_all_on_neutron_vlan")
add_group(group="system_test.strength",
systest_group="system_test.failover.destroy_controllers.first",
config_name="ceph_all_on_neutron_vlan")
add_group(group="system_test.strength",
systest_group="system_test.failover.destroy_controllers.second",
config_name="1ctrl_ceph_2ctrl_1comp_1comp_ceph_neutronVLAN")
add_group(group="fuel_master_migrate",
systest_group="system_test.fuel_migration",
config_name="1ctrl_1comp_neutronVLAN")
add_group(group="fuel_master_migrate",
systest_group="system_test.fuel_migration",
config_name="1ctrl_1comp_neutronTUN")
def get_groups(only_groups=None, exclude=None):
"""Get groups from Proboscis register and count them children"""
groups_childs = {}
groups = {}
if only_groups and isinstance(only_groups, list):
groups = {g: DEFAULT_REGISTRY.groups[g]
for g in DEFAULT_REGISTRY.groups if g in only_groups}
groups.update({g: Repository.index[g]
for g in Repository.index if g in only_groups})
else:
groups = DEFAULT_REGISTRY.groups.copy()
groups.update({g: Repository.index[g] for g in Repository.index})
for group_name, group in groups.items():
klass_entries = set()
entries_in_class = set()
if (exclude and
isinstance(exclude, list) and
any([e in group_name for e in exclude])):
continue
if hasattr(group, 'entries'):
for entry in group.entries:
if isinstance(entry, proboscis.core.TestMethodClassEntry):
klass_entries.add(entry)
for klass in klass_entries:
entries_in_class.update(set(klass.children))
child = set(group.entries) - entries_in_class - klass_entries
for klass in klass_entries:
if (klass.used_by_factory and
base_actions_factory.BaseActionsFactory in
klass.home.__mro__):
child.add(klass)
else:
child.update(set(klass.children))
else:
child = [g for g in group
if base_actions_factory.BaseActionsFactory in g.__mro__]
groups_childs[group_name] = child
return groups_childs
def case_factory(baseclass, configs):
"""Return list of instance """
# configs = get_configs()
return [baseclass.caseclass_factory(g)(c)
for g, c in config_filter(configs).items()]
def case_filter(groups=None):
"""Create Proboscis factories for selected groups. For all by default"""
if groups is None:
return set(Repository)
cases = set()
for g in groups:
if g in Repository.index:
cases.update(Repository.index[g])
return cases
def reg_factory(cases, configs):
def ret():
out = []
for c in cases:
out.extend(case_factory(c, configs))
return out
globals()['system_test_factory'] = factory(ret)
def split_group_config(group):
m = re.search('([\w\.]*)\((\w*)\)', group)
if m:
return m.groups()
def register_system_test_cases(groups=None, configs=None):
to_remove = []
to_add = []
for group in groups:
g_c = split_group_config(group)
if g_c:
g, c = g_c
to_add.append(g)
if configs is None:
configs = []
configs.append(c)
to_remove.append(group)
for one in to_remove:
groups.remove(one)
for one in to_add:
groups.append(one)
cases = case_filter(groups)
configs = config_filter(configs)
if cases:
reg_factory(cases, configs)
logger,
define_custom_groups,
tests_directory,
collect_yamls,
get_path_to_config,
get_list_confignames,
get_basepath,
]

View File

@ -0,0 +1,28 @@
# Copyright 2016 Mirantis, Inc.
#
# 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 .base import BaseActions
from .fuelmaster_actions import FuelMasterActions
from .vcenter_actions import VMwareActions
from .strength_actions import StrengthActions
from .strength_actions import FillRootActions
__all__ = [
BaseActions,
FuelMasterActions,
VMwareActions,
StrengthActions,
FillRootActions
]

View File

@ -1,4 +1,4 @@
# Copyright 2015 Mirantis, Inc.
# Copyright 2015-2016 Mirantis, Inc.
#
# 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
@ -22,17 +22,18 @@ from fuelweb_test.helpers.utils import TimeStat
from fuelweb_test import settings as test_settings
from system_test import logger
from system_test.tests import base_actions_factory
from system_test.tests.ostf_base_actions import HealthCheckActions
from system_test.tests.plugins_actions import PluginsActions
from system_test import action
from system_test import nested_action
from system_test import deferred_decorator
from system_test.actions.ostf_actions import HealthCheckActions
from system_test.actions.plugins_actions import PluginsActions
from system_test.core.discover import load_yaml
from system_test.helpers.decorators import make_snapshot_if_step_fail
from system_test.helpers.decorators import deferred_decorator
from system_test.helpers.decorators import action
from system_test.helpers.decorators import nested_action
from system_test.helpers.utils import load_yaml
class PrepareBase(base_actions_factory.BaseActionsFactory):
class PrepareActions(object):
"""Base class with prepare actions
_start_case - runned before test case start
@ -121,6 +122,7 @@ class PrepareBase(base_actions_factory.BaseActionsFactory):
"""Bootstrap slave and make snapshot
Use slaves parameter from case section
"""
slaves = int(self.full_config['template']['slaves'])
snapshot_name = "ready_with_{}_slaves".format(slaves)
@ -137,6 +139,7 @@ class PrepareBase(base_actions_factory.BaseActionsFactory):
"""Revert bootstrapped nodes
Skip if snapshot with cluster exists
"""
self.check_run(self.env_config['name'])
slaves = int(self.full_config['template']['slaves'])
@ -154,7 +157,7 @@ class PrepareBase(base_actions_factory.BaseActionsFactory):
]
class ActionsBase(PrepareBase, HealthCheckActions, PluginsActions):
class BaseActions(PrepareActions, HealthCheckActions, PluginsActions):
"""Basic actions for acceptance cases
For choosing action order use actions_order variable, set list of actions
@ -165,21 +168,18 @@ class ActionsBase(PrepareBase, HealthCheckActions, PluginsActions):
add_nodes - add nodes to environment
deploy_cluster - deploy en environment
network_check - run network check
reset_cluster - reset an environment (NotImplemented)
delete_cluster - delete en environment (NotImplemented)
stop_deploy - stop deploying of environment (NotImplemented)
reset_cluster - reset an environment
delete_cluster - delete en environment
stop_deploy - stop deploying of environment
"""
est_duration = None
base_group = None
actions_order = None
def __init__(self, config_file=None):
super(ActionsBase, self).__init__()
self.config_file = config_file
self.cluster_id = None
self.assigned_slaves = set()
self.scale_step = 0
cluster_id = None
assigned_slaves = set()
scale_step = 0
def _add_node(self, nodes_list):
"""Add nodes to Environment"""
@ -200,6 +200,25 @@ class ActionsBase(PrepareBase, HealthCheckActions, PluginsActions):
name))
self.fuel_web.update_nodes(self.cluster_id, nodes)
def _del_node(self, nodes_list):
"""Delete nodes from Environment"""
logger.info("Delete nodes from env {}".format(self.cluster_id))
nodes = {}
for node in nodes_list:
cluster_nodes = self.fuel_web.get_nailgun_cluster_nodes_by_roles(
self.cluster_id, node['roles'])
for i in xrange(node['count']):
dnode = self.fuel_web.get_devops_node_by_nailgun_node(
cluster_nodes[i])
self.assigned_slaves.remove(dnode.name)
nodes[dnode.name] = node['roles']
logger.info("Delete node {} with role {}".format(
dnode.name, node['roles']))
self.fuel_web.update_nodes(self.cluster_id, nodes, False, True)
@deferred_decorator([make_snapshot_if_step_fail])
@action
def create_env(self):
@ -208,6 +227,7 @@ class ActionsBase(PrepareBase, HealthCheckActions, PluginsActions):
For configure Environment use environment-config section in config file
Skip action if we have snapshot with Environment name
"""
self.check_run(self.env_config['name'])
@ -265,6 +285,7 @@ class ActionsBase(PrepareBase, HealthCheckActions, PluginsActions):
Used sub-section nodes in environment-config section
Skip action if cluster doesn't exist
"""
if self.cluster_id is None:
raise SkipTest()
@ -277,6 +298,7 @@ class ActionsBase(PrepareBase, HealthCheckActions, PluginsActions):
"""Deploy environment
Skip action if cluster doesn't exist
"""
if self.cluster_id is None:
raise SkipTest()
@ -303,6 +325,7 @@ class ActionsBase(PrepareBase, HealthCheckActions, PluginsActions):
"""Run network checker
Skip action if cluster doesn't exist
"""
if self.cluster_id is None:
raise SkipTest()
@ -348,9 +371,47 @@ class ActionsBase(PrepareBase, HealthCheckActions, PluginsActions):
@deferred_decorator([make_snapshot_if_step_fail])
@action
def scale_node(self):
"""Scale node in cluster"""
"""Scale node in cluster
For add nodes with role use scale_nodes in yaml with action add in
step::
scale_nodes:
- - roles:
- controller
count: 2
action: add
For remove nodes with role use scale_nodes in yaml with action delete
in step:::
scale_nodes:
- - roles:
- controller
count: 2
action: delete
Step may contain add and remove action together::
scale_nodes:
- - roles:
- compute
count: 2
action: add
- - roles:
- ceph-osd
count: 1
action: delete
"""
step_config = self.env_config['scale_nodes'][self.scale_step]
self._add_node(step_config)
for node in step_config:
if node['action'] == 'add':
self._add_node([node])
elif node['action'] == 'delete':
self._del_node([node])
else:
logger.error("Unknow scale action: {}".format(node['action']))
self.scale_step += 1
@deferred_decorator([make_snapshot_if_step_fail])
@ -366,18 +427,3 @@ class ActionsBase(PrepareBase, HealthCheckActions, PluginsActions):
"""Delete environment"""
cluster_id = self.cluster_id
self.fuel_web.delete_env_wait(cluster_id)
class FuelMasterActions(base_actions_factory.BaseActionsFactory):
"""Actions specific only to Fuel Master node
_action_check_containers - check that docker containers are up
and running
"""
@deferred_decorator([make_snapshot_if_step_fail])
@action
def check_containers(self):
"""Check that containers are up and running"""
logger.info("Check containers")
self.env.docker_actions.wait_for_ready_containers(timeout=60 * 30)

View File

@ -0,0 +1,34 @@
# Copyright 2015-2016 Mirantis, Inc.
#
# 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 system_test import action
from system_test import deferred_decorator
from system_test import logger
from system_test.helpers.decorators import make_snapshot_if_step_fail
class FuelMasterActions(object):
"""Actions specific only to Fuel Master node
check_containers - check that docker containers are up
and running
"""
@deferred_decorator([make_snapshot_if_step_fail])
@action
def check_containers(self):
"""Check that containers are up and running"""
logger.info("Check containers")
self.env.docker_actions.wait_for_ready_containers(timeout=60 * 30)

View File

@ -14,16 +14,18 @@
from proboscis import SkipTest
from system_test import deferred_decorator
from system_test import action
from system_test.helpers.decorators import make_snapshot_if_step_fail
from system_test.helpers.decorators import deferred_decorator
from system_test.helpers.decorators import action
from system_test.tests import base_actions_factory
class HealthCheckActions(base_actions_factory.BaseActionsFactory):
class HealthCheckActions(object):
"""Basic actions for OSTF tests
health_check - run sanity and smoke OSTF tests
health_check_sanity_smoke_ha - run sanity, smoke and ha OSTF tests
health_check_ha - run ha OSTF tests
"""
@deferred_decorator([make_snapshot_if_step_fail])
@action

View File

@ -17,15 +17,16 @@ import os
from proboscis.asserts import assert_true, assert_equal
from fuelweb_test.helpers import checkers
from system_test import logger
from system_test.helpers.decorators import action
from system_test.helpers.decorators import deferred_decorator
from system_test import action
from system_test import deferred_decorator
from system_test import nested_action
from system_test.helpers.decorators import make_snapshot_if_step_fail
from system_test.helpers.decorators import nested_action
from system_test.tests import base_actions_factory
class PluginsActions(base_actions_factory.BaseActionsFactory):
class PluginsActions(object):
plugin_name = None
plugin_path = None

View File

@ -24,21 +24,17 @@ from fuelweb_test.helpers.pacemaker import get_pacemaker_nodes_attributes
from fuelweb_test.helpers.pacemaker import get_pcs_nodes
from fuelweb_test.helpers.pacemaker import parse_pcs_status_xml
from system_test.tests import actions_base
from system_test.helpers.decorators import make_snapshot_if_step_fail
from system_test.helpers.decorators import deferred_decorator
from system_test.helpers.decorators import action
from system_test import logger
from system_test import deferred_decorator
from system_test import action
from system_test.helpers.decorators import make_snapshot_if_step_fail
class StrengthBaseActions(actions_base.ActionsBase):
class StrengthActions(object):
def __init__(self, config=None):
super(StrengthBaseActions, self).__init__(config)
self.destroyed_devops_nodes = []
self.ostf_tests_should_failed = 0
self.os_service_should_failed = 0
destroyed_devops_nodes = []
ostf_tests_should_failed = 0
os_service_should_failed = 0
def _destroy_controller(self, devops_node_name):
logger.info("Suspend {} node".format(devops_node_name))
@ -110,22 +106,20 @@ class StrengthBaseActions(actions_base.ActionsBase):
self.destroyed_devops_nodes)
class FillRootBaseActions(actions_base.ActionsBase):
class FillRootActions(object):
def __init__(self, config=None):
super(FillRootBaseActions, self).__init__(config)
self.ostf_tests_should_failed = 0
self.primary_controller = None
self.primary_controller_fqdn = None
self.primary_controller_space_on_root = 0
self.disk_monitor_limit = 512
self.rabbit_disk_free_limit = 5
self.pacemaker_restart_timeout = 600
self.pcs_check_timeout = 300
self.primary_controller_space_to_filled = 0
self.pcs_status = None
self.slave_nodes_fqdn = None
self.slave_node_running_resources = None
ostf_tests_should_failed = 0
primary_controller = None
primary_controller_fqdn = None
primary_controller_space_on_root = 0
disk_monitor_limit = 512
rabbit_disk_free_limit = 5
pacemaker_restart_timeout = 600
pcs_check_timeout = 300
primary_controller_space_to_filled = 0
pcs_status = None
slave_nodes_fqdn = None
slave_node_running_resources = None
@deferred_decorator([make_snapshot_if_step_fail])
@action

View File

@ -0,0 +1,149 @@
# Copyright 2016 Mirantis, Inc.
#
# 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 proboscis.asserts import assert_true
from system_test import logger
from system_test import deferred_decorator
from system_test import action
from system_test.helpers.decorators import make_snapshot_if_step_fail
class VMwareActions(object):
"""VMware vCenter/DVS related actions"""
plugin_version = None
@deferred_decorator([make_snapshot_if_step_fail])
@action
def enable_plugin(self):
"""Enable plugin for Fuel"""
assert_true(self.plugin_name, "plugin_name is not specified")
msg = "Plugin couldn't be enabled. Check plugin version. Test aborted"
assert_true(
self.fuel_web.check_plugin_exists(
self.cluster_id,
self.plugin_name),
msg)
plugin_data = self.fuel_web.get_plugin_data(self.cluster_id,
self.plugin_name,
self.plugin_version)
options = {'metadata/enabled': True,
'metadata/chosen_id': plugin_data['metadata']['plugin_id']}
self.fuel_web.update_plugin_data(self.cluster_id,
self.plugin_name, options)
@deferred_decorator([make_snapshot_if_step_fail])
@action
def configure_dvs_plugin(self):
"""Configure DVS plugin"""
msg = "Plugin couldn't be enabled. Check plugin version. Test aborted"
assert_true(
self.fuel_web.check_plugin_exists(
self.cluster_id,
self.plugin_name),
msg)
options = {'vmware_dvs_net_maps/value': self.full_config[
'template']['cluster_template']['settings']['vmware_dvs'][
'dvswitch_name']}
self.fuel_web.update_plugin_settings(
self.cluster_id, self.plugin_name, self.plugin_version, options)
@deferred_decorator([make_snapshot_if_step_fail])
@action
def configure_vcenter(self):
"""Configure vCenter settings"""
vmware_vcenter = self.env_settings['vmware_vcenter']
vcenter_value = {
"glance": {"vcenter_username": "",
"datacenter": "",
"vcenter_host": "",
"vcenter_password": "",
"datastore": ""
},
"availability_zones": [
{"vcenter_username": vmware_vcenter['settings']['user'],
"nova_computes": [],
"vcenter_host": vmware_vcenter['settings']['host'],
"az_name": vmware_vcenter['settings']['az'],
"vcenter_password": vmware_vcenter['settings']['pwd']
}]
}
clusters = vmware_vcenter['nova-compute']
nodes = self.fuel_web.client.list_cluster_nodes(self.cluster_id)
roles = ['compute-vmware']
comp_vmware_nodes = [n for n in nodes if set(roles) <=
set(n['pending_roles'])]
for cluster in clusters:
cluster_name = cluster['cluster']
srv_name = cluster['srv_name']
datastore = cluster['datastore']
if cluster['target_node'] == 'compute-vmware':
node = comp_vmware_nodes.pop()
target_node = node['hostname']
else:
target_node = cluster['target_node']
vcenter_value["availability_zones"][0]["nova_computes"].append(
{"vsphere_cluster": cluster_name,
"service_name": srv_name,
"datastore_regex": datastore,
"target_node": {
"current": {"id": target_node,
"label": target_node},
"options": [{"id": target_node,
"label": target_node}, ]},
}
)
if vmware_vcenter['glance']['enable']:
attributes = self.fuel_web.client.get_cluster_attributes(
self.cluster_id)
attributes['editable']['storage']['images_vcenter']['value'] =\
vmware_vcenter['glance']['enable']
self.fuel_web.client.update_cluster_attributes(self.cluster_id,
attributes)
vcenter_value["glance"]["vcenter_host"] = vmware_vcenter[
'glance']['host']
vcenter_value["glance"]["vcenter_username"] = vmware_vcenter[
'glance']['user']
vcenter_value["glance"]["vcenter_password"] = vmware_vcenter[
'glance']['pwd']
vcenter_value["glance"]["datacenter"] = vmware_vcenter[
'glance']['datacenter']
vcenter_value["glance"]["datastore"] = vmware_vcenter[
'glance']['datastore']
logger.info('Configuring vCenter...')
vmware_attr = \
self.fuel_web.client.get_cluster_vmware_attributes(self.cluster_id)
vcenter_data = vmware_attr['editable']
vcenter_data['value'] = vcenter_value
logger.debug("Try to update cluster with next "
"vmware_attributes {0}".format(vmware_attr))
self.fuel_web.client.update_cluster_vmware_attributes(self.cluster_id,
vmware_attr)
logger.debug("Attributes of cluster have been updated")

View File

@ -0,0 +1,23 @@
# Copyright 2016 Mirantis, Inc.
#
# 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 .factory import ActionsFactory
from .repository import Repository
__all__ = [
ActionsFactory,
Repository,
]

View File

@ -0,0 +1,80 @@
# Copyright 2016 Mirantis, Inc.
#
# 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 proboscis import register
from system_test.core.discover import get_configs
from system_test.core.repository import register_system_test_cases
tests_directory = [
'fuelweb_test/tests',
'system_test/tests',
'gates_tests'
]
def cached_add_group(yamls):
def add(group, systest_group, config_name,
validate_config=True):
"""Add user friendly group
:type group_name: str
:type systest_group: str
:type config_name: str
"""
if validate_config and config_name not in yamls:
raise NameError("Config {} not found".format(config_name))
register_system_test_cases(groups=[systest_group],
configs=[config_name])
register(groups=[group],
depends_on_groups=[
"{systest_group}({config_name})".format(
systest_group=systest_group,
config_name=config_name)])
return add
def define_custom_groups():
"""Map user friendly group name to system test groups
groups - contained user friendly alias
depends - contained groups which should be runned
"""
add_group = cached_add_group(get_configs())
add_group(group="system_test.ceph_ha",
systest_group="system_test.deploy_and_check_radosgw",
config_name="ceph_all_on_neutron_vlan")
add_group(group="filling_root",
systest_group="system_test.failover.filling_root",
config_name="ceph_all_on_neutron_vlan")
add_group(group="system_test.strength",
systest_group="system_test.failover.destroy_controllers.first",
config_name="ceph_all_on_neutron_vlan")
add_group(group="system_test.strength",
systest_group="system_test.failover.destroy_controllers.second",
config_name="1ctrl_ceph_2ctrl_1comp_1comp_ceph_neutronVLAN")
add_group(group="fuel_master_migrate",
systest_group="system_test.fuel_migration",
config_name="1ctrl_1comp_neutronVLAN")
add_group(group="fuel_master_migrate",
systest_group="system_test.fuel_migration",
config_name="1ctrl_1comp_neutronTUN")

View File

@ -0,0 +1,50 @@
# Copyright 2016 Mirantis, Inc.
#
# 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 inspect
import collections
from system_test.core.repository import Repository
def testcase(groups):
"""Use this decorator for mark a test case class"""
def testcase_decorator(cls):
if not inspect.isclass(cls):
raise TypeError("Decorator @testcase should used only "
"with classes")
if not isinstance(groups, collections.Sequence):
raise TypeError("Use list for groups")
cls.get_actions_order()
setattr(cls, '_base_groups', groups)
Repository.add(cls)
return cls
return testcase_decorator
def action(method):
setattr(method, '_action_method_', True)
return method
def nested_action(method):
setattr(method, '_nested_action_method_', True)
return staticmethod(method)
def deferred_decorator(decorator_list):
def real_decorator(func):
setattr(func, '_deferred_decorator_', decorator_list)
return func
return real_decorator

View File

@ -13,6 +13,115 @@
# under the License.
import os.path
import yaml
def get_basepath():
import system_test
return os.path.join(
os.path.dirname(os.path.dirname(system_test.__file__)))
def get_list_confignames(filelist):
"""Get list of config name from file list"""
return map(get_configname, filelist)
def get_configname(path):
"""Get config name from path to yaml file"""
return os.path.splitext(os.path.basename(path))[0]
def get_path_to_config():
"""Find path to directory with config files"""
import system_test
return os.path.join(os.path.dirname(system_test.__file__),
'tests_templates/tests_configs')
def get_path_to_template():
"""Find path to directory with templates files"""
import system_test
return os.path.join(os.path.dirname(system_test.__file__),
'tests_templates')
def collect_yamls(path):
"""Walk through config directory and find all yaml files"""
ret = []
for r, d, f in os.walk(path):
for one in f:
if os.path.splitext(one)[1] in ('.yaml', '.yml'):
ret.append(os.path.join(r, one))
return ret
def load_yaml(path):
"""Load yaml file from path"""
def yaml_include(loader, node):
file_name = os.path.join(get_path_to_template(), node.value)
if not os.path.isfile(file_name):
raise ValueError(
"Cannot load the template {0} : include file {1} "
"doesn't exist.".format(path, file_name))
return yaml.load(open(file_name))
def yaml_get_env_variable(loader, node):
if not node.value.strip():
raise ValueError("Environment variable is required after {tag} in "
"{filename}".format(tag=node.tag,
filename=loader.name))
node_value = node.value.split(',', 1)
# Get the name of environment variable
env_variable = node_value[0].strip()
# Get the default value for environment variable if it exists in config
if len(node_value) > 1:
default_val = node_value[1].strip()
else:
default_val = None
value = os.environ.get(env_variable, default_val)
if value is None:
raise ValueError("Environment variable {var} is not set from shell"
" environment! No default value provided in file "
"{filename}".format(var=env_variable,
filename=loader.name))
return yaml.load(value)
yaml.add_constructor("!include", yaml_include)
yaml.add_constructor("!os_env", yaml_get_env_variable)
return yaml.load(open(path))
def find_duplicates(yamls):
dup = {}
for one in yamls:
name = os.path.basename(one)
if name in dup:
dup[name].append(one)
else:
dup[name] = [one]
return {k: v for k, v in dup.items() if len(v) > 1}
def get_configs():
"""Return list of dict environment configurations"""
yamls = collect_yamls(get_path_to_config())
dup = find_duplicates(yamls)
if dup:
raise NameError(
"Found duplicate files in templates. "
"Name of template should be unique. Errors: {}".format(dup))
return {get_configname(y): y for y in yamls}
def config_filter(configs=None):
if configs is None:
return get_configs()
return {k: v for k, v in get_configs().items() if k in configs}
def discover_test_files(basedir, dirs):

View File

@ -13,15 +13,14 @@
# under the License.
import functools
import types
from proboscis import after_class
from proboscis import before_class
from proboscis import test
from fuelweb_test.helpers.utils import TimeStat
from fuelweb_test.tests import base_test_case
from system_test.helpers import utils
from system_test import logger
@ -45,7 +44,23 @@ def step_start_stop(func):
return wrapper
class BaseActionsFactory(base_test_case.TestBasic):
def copy_func(f, name=None):
"""
:param f:
:param name:
:return: a function with same code, globals, defaults, closure,
and name (or provide a new name)
"""
fn = types.FunctionType(f.__code__, f.__globals__, name or f.__name__,
f.__defaults__, f.__closure__)
# in case f was given attrs (note this dict is a shallow copy):
fn.__dict__.update(f.__dict__)
return fn
class ActionsFactory(object):
@classmethod
def get_actions(cls):
@ -66,11 +81,11 @@ class BaseActionsFactory(base_test_case.TestBasic):
for action in cls.actions_order:
try:
action_method = actions_method[action]
except KeyError:
except KeyError as e:
import inspect
source = inspect.getsourcelines(inspect.getmodule(cls))[0]
counted_data = [n for n in enumerate(source)]
line_num = [n for (n, l) in counted_data if 'ddd' in l][0]
line_num = [n for (n, l) in counted_data if str(e) in l][0]
cutted = counted_data[line_num - 4:line_num + 4]
cutted = [(n, l[:-1] + " " * 20 + "<====\n"
if n == line_num else l)
@ -114,7 +129,7 @@ class BaseActionsFactory(base_test_case.TestBasic):
step,
n_action)
method = utils.copy_func(action['method'], step_method_name)
method = copy_func(action['method'], step_method_name)
_step_name = getattr(action['method'],
"__doc__").splitlines()[0]
setattr(method, "_step_name", "Step {:03d}. {}".format(step,
@ -150,14 +165,14 @@ class BaseActionsFactory(base_test_case.TestBasic):
depends_on=depends)
# Create before case methods, start case and setup
start_method = utils.copy_func(
start_method = copy_func(
getattr(cls, "_start_case"),
"{}.StartCase".format(class_name))
test_steps["{}.StartCase".format(class_name)] = before_class(
start_method)
if hasattr(cls, 'case_setup'):
setup_method = utils.copy_func(
setup_method = copy_func(
getattr(cls, "case_setup"),
"{}.CaseSetup".format(class_name))
setattr(setup_method, "_step_name", "CaseSetup")
@ -165,7 +180,7 @@ class BaseActionsFactory(base_test_case.TestBasic):
step_start_stop(setup_method), runs_after=[start_method])
if hasattr(cls, 'case_teardown'):
teardown_method = utils.copy_func(
teardown_method = copy_func(
getattr(cls, "case_teardown"),
"{}.CaseTeardown".format(class_name))
setattr(teardown_method, "_step_name", "CaseTeardown")
@ -175,7 +190,7 @@ class BaseActionsFactory(base_test_case.TestBasic):
teardown_method = None
# Create case methods, teardown and finish case
finish_method = utils.copy_func(
finish_method = copy_func(
getattr(cls, "_finish_case"),
"{}.FinishCase".format(class_name))
test_steps["{}.FinishCase".format(class_name)] = after_class(

View File

@ -14,6 +14,15 @@
from fuelweb_test.helpers import metaclasses
import re
import proboscis.core
from proboscis import factory
from proboscis.decorators import DEFAULT_REGISTRY
from system_test.tests import ActionTest
from system_test.core.discover import config_filter
class TestCaseRepository(set):
@ -72,5 +81,108 @@ class TestCaseRepository(set):
raise AttributeError("'TestCaseRepository' object has no attribute "
" 'update'")
Repository = TestCaseRepository()
def get_groups(only_groups=None, exclude=None):
"""Get groups from Proboscis register and count them children"""
groups_childs = {}
groups = {}
if only_groups and isinstance(only_groups, list):
groups = {g: DEFAULT_REGISTRY.groups[g]
for g in DEFAULT_REGISTRY.groups if g in only_groups}
groups.update({g: Repository.index[g]
for g in Repository.index if g in only_groups})
else:
groups = DEFAULT_REGISTRY.groups.copy()
groups.update({g: Repository.index[g] for g in Repository.index})
for group_name, group in groups.items():
klass_entries = set()
entries_in_class = set()
if (exclude and
isinstance(exclude, list) and
any([e in group_name for e in exclude])):
continue
if hasattr(group, 'entries'):
for entry in group.entries:
if isinstance(entry, proboscis.core.TestMethodClassEntry):
klass_entries.add(entry)
for klass in klass_entries:
entries_in_class.update(set(klass.children))
child = set(group.entries) - entries_in_class - klass_entries
for klass in klass_entries:
if (klass.used_by_factory and
ActionTest in
klass.home.__mro__):
child.add(klass)
else:
child.update(set(klass.children))
else:
child = [g for g in group
if ActionTest in g.__mro__]
groups_childs[group_name] = child
return groups_childs
def case_filter(groups=None):
"""Create Proboscis factories for selected groups. For all by default"""
if groups is None:
return set(Repository)
cases = set()
for g in groups:
if g in Repository.index:
cases.update(Repository.index[g])
return cases
def case_factory(baseclass, configs):
"""Return list of instance """
return [baseclass.caseclass_factory(g)(c)
for g, c in config_filter(configs).items()]
def reg_factory(cases, configs):
def ret():
out = []
for c in cases:
out.extend(case_factory(c, configs))
return out
globals()['system_test_factory'] = factory(ret)
def split_group_config(group):
m = re.search('([\w\.]*)\((\w*)\)', group)
if m:
return m.groups()
def register_system_test_cases(groups=None, configs=None):
to_remove = []
to_add = []
for group in groups:
g_c = split_group_config(group)
if g_c:
g, c = g_c
to_add.append(g)
if configs is None:
configs = []
configs.append(c)
to_remove.append(group)
for one in to_remove:
groups.remove(one)
for one in to_add:
groups.append(one)
cases = case_filter(groups)
configs = config_filter(configs)
if cases:
reg_factory(cases, configs)

View File

@ -15,35 +15,15 @@
import functools
import traceback
import hashlib
import inspect
import collections
from proboscis import SkipTest
from fuelweb_test.helpers.utils import pull_out_logs_via_ssh
from fuelweb_test.helpers.decorators import create_diagnostic_snapshot
from system_test import Repository
from system_test import logger
def deferred_decorator(decorator_list):
def real_decorator(func):
setattr(func, '_deferred_decorator_', decorator_list)
return func
return real_decorator
def action(method):
setattr(method, '_action_method_', True)
return method
def nested_action(method):
setattr(method, '_nested_action_method_', True)
return staticmethod(method)
def make_snapshot_if_step_fail(func):
"""Generate diagnostic snapshot if step fail.
@ -102,18 +82,3 @@ def make_snapshot_if_step_fail(func):
raise test_exception
return result
return wrapper
def testcase(groups):
"""Use this decorator for mark a test case class"""
def testcase_decorator(cls):
if not inspect.isclass(cls):
raise TypeError("Decorator @testcase should used only "
"with classes")
if not isinstance(groups, collections.Sequence):
raise TypeError("Use list for groups")
cls.get_actions_order()
setattr(cls, '_base_groups', groups)
Repository.add(cls)
return cls
return testcase_decorator

View File

@ -1,141 +0,0 @@
# Copyright 2015 Mirantis, Inc.
#
# 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 yaml
import os
import types
def copy_func(f, name=None):
"""
:param f:
:param name:
:return: a function with same code, globals, defaults, closure,
and name (or provide a new name)
"""
fn = types.FunctionType(f.__code__, f.__globals__, name or f.__name__,
f.__defaults__, f.__closure__)
# in case f was given attrs (note this dict is a shallow copy):
fn.__dict__.update(f.__dict__)
return fn
def get_basepath():
import system_test
return os.path.join(
os.path.dirname(os.path.dirname(system_test.__file__)))
def get_list_confignames(filelist):
"""Get list of config name from file list"""
return map(get_configname, filelist)
def get_configname(path):
"""Get config name from path to yaml file"""
return os.path.splitext(os.path.basename(path))[0]
def get_path_to_config():
"""Find path to directory with config files"""
import system_test
return os.path.join(os.path.dirname(system_test.__file__),
'tests_templates/tests_configs')
def get_path_to_template():
"""Find path to directory with templates files"""
import system_test
return os.path.join(os.path.dirname(system_test.__file__),
'tests_templates')
def collect_yamls(path):
"""Walk through config directory and find all yaml files"""
ret = []
for r, d, f in os.walk(path):
for one in f:
if os.path.splitext(one)[1] in ('.yaml', '.yml'):
ret.append(os.path.join(r, one))
return ret
def load_yaml(path):
"""Load yaml file from path"""
def yaml_include(loader, node):
file_name = os.path.join(get_path_to_template(), node.value)
if not os.path.isfile(file_name):
raise ValueError(
"Cannot load the template {0} : include file {1} "
"doesn't exist.".format(path, file_name))
return yaml.load(open(file_name))
def yaml_get_env_variable(loader, node):
if not node.value.strip():
raise ValueError("Environment variable is required after {tag} in "
"{filename}".format(tag=node.tag,
filename=loader.name))
node_value = node.value.split(',', 1)
# Get the name of environment variable
env_variable = node_value[0].strip()
# Get the default value for environment variable if it exists in config
if len(node_value) > 1:
default_val = node_value[1].strip()
else:
default_val = None
value = os.environ.get(env_variable, default_val)
if value is None:
raise ValueError("Environment variable {var} is not set from shell"
" environment! No default value provided in file "
"{filename}".format(var=env_variable,
filename=loader.name))
return yaml.load(value)
yaml.add_constructor("!include", yaml_include)
yaml.add_constructor("!os_env", yaml_get_env_variable)
return yaml.load(open(path))
def find_duplicates(yamls):
dup = {}
for one in yamls:
name = os.path.basename(one)
if name in dup:
dup[name].append(one)
else:
dup[name] = [one]
return {k: v for k, v in dup.items() if len(v) > 1}
def get_configs():
"""Return list of dict environment configurations"""
yamls = collect_yamls(get_path_to_config())
dup = find_duplicates(yamls)
if dup:
raise NameError(
"Found duplicate files in templates. "
"Name of template should be unique. Errors: {}".format(dup))
return {get_configname(y): y for y in yamls}
def config_filter(configs=None):
if configs is None:
return get_configs()
return {k: v for k, v in get_configs().items() if k in configs}

View File

@ -0,0 +1,20 @@
# Copyright 2016 Mirantis, Inc.
#
# 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 .base import ActionTest
__all__ = [
ActionTest
]

24
system_test/tests/base.py Normal file
View File

@ -0,0 +1,24 @@
# Copyright 2016 Mirantis, Inc.
#
# 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 fuelweb_test.tests import base_test_case
from system_test.core import ActionsFactory
class ActionTest(base_test_case.TestBasic, ActionsFactory):
"""ActionTest is TestBasic wraper for system tests"""
def __init__(self, config_file=None):
super(ActionTest, self).__init__()
self.config_file = config_file

View File

@ -12,16 +12,19 @@
# License for the specific language governing permissions and limitations
# under the License.
from system_test import testcase
from fuelweb_test.settings import EXAMPLE_PLUGIN_PATH
from system_test.tests.actions_base import ActionsBase
from system_test import testcase
from system_test.tests import ActionTest
from system_test.actions import BaseActions
@testcase(groups=['system_test',
'system_test.plugins',
'system_test.plugins.example_plugin',
'system_test.plugins.example_plugin.simple'])
class DeployWithPluginExample(ActionsBase):
class DeployWithPluginExample(ActionTest, BaseActions):
"""Deploy cluster with one controller and example plugin
Scenario:
@ -59,7 +62,7 @@ class DeployWithPluginExample(ActionsBase):
'system_test.plugins',
'system_test.plugins.example_plugin',
'system_test.plugins.example_plugin.simple_scale'])
class DeployScaleWithPluginExample(ActionsBase):
class DeployScaleWithPluginExample(ActionTest, BaseActions):
"""Deploy and scale cluster in ha mode with example plugin
Scenario:

View File

@ -14,18 +14,21 @@
from fuelweb_test.settings import EXAMPLE_PLUGIN_V3_PATH
from system_test import testcase
from system_test import deferred_decorator
from system_test import action
from system_test.tests import ActionTest
from system_test.actions import BaseActions
from system_test.helpers.decorators import make_snapshot_if_step_fail
from system_test.helpers.decorators import deferred_decorator
from system_test.helpers.decorators import action
from system_test.tests.actions_base import ActionsBase
@testcase(groups=['system_test',
'system_test.plugins',
'system_test.plugins.example_plugin_v3',
'system_test.plugins.example_plugin_v3.simple'])
class DeployWithPluginExampleV3(ActionsBase):
class DeployWithPluginExampleV3(ActionTest, BaseActions):
"""Deploy cluster with one controller and example plugin v3
Scenario:

View File

@ -13,17 +13,20 @@
# under the License.
from system_test import testcase
from system_test.tests.strength import strength_base
from system_test import deferred_decorator
from system_test import action
from system_test.tests import ActionTest
from system_test.actions import BaseActions
from system_test.actions import StrengthActions
from system_test.helpers.decorators import make_snapshot_if_step_fail
from system_test.helpers.decorators import deferred_decorator
from system_test.helpers.decorators import action
@testcase(groups=['system_test',
'system_test.failover',
'system_test.failover.destroy_controllers',
'system_test.failover.destroy_controllers.first'])
class StrengthDestroyFirstController(strength_base.StrengthBaseActions):
class StrengthDestroyFirstController(ActionTest, BaseActions, StrengthActions):
"""Destroy two controllers and check pacemaker status is correct
Scenario:
@ -73,7 +76,8 @@ class StrengthDestroyFirstController(strength_base.StrengthBaseActions):
'system_test.failover',
'system_test.failover.destroy_controllers',
'system_test.failover.destroy_controllers.second'])
class StrengthDestroySecondController(strength_base.StrengthBaseActions):
class StrengthDestroySecondController(ActionTest, BaseActions,
StrengthActions):
"""Destroy two controllers and check pacemaker status is correct
Scenario:

View File

@ -14,15 +14,15 @@
from system_test import testcase
from system_test.tests.strength import strength_base
from system_test.tests import ActionTest
from system_test.actions import BaseActions
from system_test.actions import FillRootActions
@testcase(groups=['system_test',
'system_test.failover',
'system_test.failover.filling_root'])
class FillRootPrimaryController(
strength_base.FillRootBaseActions
):
class FillRootPrimaryController(ActionTest, BaseActions, FillRootActions):
"""Fill root filesystem on primary controller and check pacemaker
Scenario:

View File

@ -13,11 +13,12 @@
# under the License.
from system_test import testcase
from system_test.tests import actions_base
from system_test.tests import ActionTest
from system_test.actions import BaseActions
@testcase(groups=['system_test', 'system_test.create_deploy_ostf'])
class CreateDeployOstf(actions_base.ActionsBase):
class CreateDeployOstf(ActionTest, BaseActions):
"""Case deploy Environment
Scenario:

View File

@ -13,11 +13,12 @@
# under the License.
from system_test import testcase
from system_test.tests import actions_base
from system_test.tests import ActionTest
from system_test.actions import BaseActions
@testcase(groups=['system_test', 'system_test.delete_after_deploy'])
class DeleteAfterDeploy(actions_base.ActionsBase):
class DeleteAfterDeploy(ActionTest, BaseActions):
"""Case deploy Environment
Scenario:

View File

@ -15,15 +15,18 @@
from proboscis.asserts import assert_true
from system_test import testcase
from system_test.tests import actions_base
from system_test.helpers.decorators import deferred_decorator
from system_test import action
from system_test import deferred_decorator
from system_test.tests import ActionTest
from system_test.actions import BaseActions
from system_test.helpers.decorators import make_snapshot_if_step_fail
from system_test.helpers.decorators import action
@testcase(groups=['system_test',
'system_test.deploy_and_check_radosgw'])
class DeployCheckRadosGW(actions_base.ActionsBase):
class DeployCheckRadosGW(ActionTest, BaseActions):
"""Deploy cluster and check RadosGW
Scenario:

View File

@ -16,19 +16,22 @@ from devops.helpers.helpers import icmp_ping
from devops.helpers.helpers import wait
from proboscis.asserts import assert_equal
from fuelweb_test import logger
from fuelweb_test.helpers import checkers
from system_test import logger
from system_test import testcase
from system_test.helpers.decorators import action
from system_test.helpers.decorators import deferred_decorator
from system_test import action
from system_test import deferred_decorator
from system_test.tests import ActionTest
from system_test.actions import BaseActions
from system_test.actions import FuelMasterActions
from system_test.helpers.decorators import make_snapshot_if_step_fail
from system_test.tests.actions_base import ActionsBase
from system_test.tests.actions_base import FuelMasterActions
@testcase(groups=['system_test', 'system_test.fuel_migration'])
class FuelMasterMigrate(ActionsBase, FuelMasterActions):
class FuelMasterMigrate(ActionTest, BaseActions, FuelMasterActions):
"""Fuel master migration to VM
Scenario:

View File

@ -13,11 +13,12 @@
# under the License.
from system_test import testcase
from system_test.tests import actions_base
from system_test.tests import ActionTest
from system_test.actions import BaseActions
@testcase(groups=['system_test', 'system_test.redeploy_after_reset'])
class RedeployAfterReset(actions_base.ActionsBase):
class RedeployAfterReset(ActionTest, BaseActions):
"""Case deploy Environment
Scenario:

View File

@ -13,11 +13,12 @@
# under the License.
from system_test import testcase
from system_test.tests import actions_base
from system_test.tests import ActionTest
from system_test.actions import BaseActions
@testcase(groups=['system_test', 'system_test.redeploy_after_stop'])
class RedeployAfterStop(actions_base.ActionsBase):
class RedeployAfterStop(ActionTest, BaseActions):
"""Case deploy Environment
Scenario:

View File

@ -12,183 +12,19 @@
# License for the specific language governing permissions and limitations
# under the License.
from proboscis.asserts import assert_true
from system_test import testcase
from system_test import logger
from system_test.helpers.decorators import make_snapshot_if_step_fail
from system_test.helpers.decorators import deferred_decorator
from system_test.helpers.decorators import action
from system_test.tests.actions_base import ActionsBase
from fuelweb_test.settings import DVS_PLUGIN_PATH
from fuelweb_test.settings import DVS_PLUGIN_VERSION
class VMwareActions(ActionsBase):
"""VMware vCenter/DVS related actions"""
plugin_version = None
@deferred_decorator([make_snapshot_if_step_fail])
@action
def enable_plugin(self):
"""Enable plugin for Fuel"""
assert_true(self.plugin_name, "plugin_name is not specified")
msg = "Plugin couldn't be enabled. Check plugin version. Test aborted"
assert_true(
self.fuel_web.check_plugin_exists(
self.cluster_id,
self.plugin_name),
msg)
plugin_data = self.fuel_web.get_plugin_data(self.cluster_id,
self.plugin_name,
self.plugin_version)
options = {'metadata/enabled': True,
'metadata/chosen_id': plugin_data['metadata']['plugin_id']}
self.fuel_web.update_plugin_data(self.cluster_id,
self.plugin_name, options)
@deferred_decorator([make_snapshot_if_step_fail])
@action
def configure_dvs_plugin(self):
"""Configure DVS plugin"""
msg = "Plugin couldn't be enabled. Check plugin version. Test aborted"
assert_true(
self.fuel_web.check_plugin_exists(
self.cluster_id,
self.plugin_name),
msg)
options = {'vmware_dvs_net_maps/value': self.full_config[
'template']['cluster_template']['settings']['vmware_dvs'][
'dvswitch_name']}
self.fuel_web.update_plugin_settings(
self.cluster_id, self.plugin_name, self.plugin_version, options)
@deferred_decorator([make_snapshot_if_step_fail])
@action
def configure_vcenter(self):
"""Configure vCenter settings"""
vmware_vcenter = self.env_settings['vmware_vcenter']
vcenter_value = {
"glance": {"vcenter_username": "",
"datacenter": "",
"vcenter_host": "",
"vcenter_password": "",
"datastore": ""
},
"availability_zones": [
{"vcenter_username": vmware_vcenter['settings']['user'],
"nova_computes": [],
"vcenter_host": vmware_vcenter['settings']['host'],
"az_name": vmware_vcenter['settings']['az'],
"vcenter_password": vmware_vcenter['settings']['pwd']
}]
}
clusters = vmware_vcenter['nova-compute']
nodes = self.fuel_web.client.list_cluster_nodes(self.cluster_id)
roles = ['compute-vmware']
comp_vmware_nodes = [n for n in nodes if set(roles) <=
set(n['pending_roles'])]
for cluster in clusters:
cluster_name = cluster['cluster']
srv_name = cluster['srv_name']
datastore = cluster['datastore']
if cluster['target_node'] == 'compute-vmware':
node = comp_vmware_nodes.pop()
target_node = node['hostname']
else:
target_node = cluster['target_node']
vcenter_value["availability_zones"][0]["nova_computes"].append(
{"vsphere_cluster": cluster_name,
"service_name": srv_name,
"datastore_regex": datastore,
"target_node": {
"current": {"id": target_node,
"label": target_node},
"options": [{"id": target_node,
"label": target_node}, ]},
}
)
if vmware_vcenter['glance']['enable']:
attributes = self.fuel_web.client.get_cluster_attributes(
self.cluster_id)
attributes['editable']['storage']['images_vcenter']['value'] =\
vmware_vcenter['glance']['enable']
self.fuel_web.client.update_cluster_attributes(self.cluster_id,
attributes)
vcenter_value["glance"]["vcenter_host"] = vmware_vcenter[
'glance']['host']
vcenter_value["glance"]["vcenter_username"] = vmware_vcenter[
'glance']['user']
vcenter_value["glance"]["vcenter_password"] = vmware_vcenter[
'glance']['pwd']
vcenter_value["glance"]["datacenter"] = vmware_vcenter[
'glance']['datacenter']
vcenter_value["glance"]["datastore"] = vmware_vcenter[
'glance']['datastore']
logger.info('Configuring vCenter...')
vmware_attr = \
self.fuel_web.client.get_cluster_vmware_attributes(self.cluster_id)
vcenter_data = vmware_attr['editable']
vcenter_data['value'] = vcenter_value
logger.debug("Try to update cluster with next "
"vmware_attributes {0}".format(vmware_attr))
self.fuel_web.client.update_cluster_vmware_attributes(self.cluster_id,
vmware_attr)
logger.debug("Attributes of cluster have been updated")
def _del_node(self, nodes_list):
"""Delete nodes from Environment"""
logger.info("Delete nodes from env {}".format(self.cluster_id))
nodes = {}
for node in nodes_list:
cluster_nodes = self.fuel_web.get_nailgun_cluster_nodes_by_roles(
self.cluster_id, node['roles'])
for i in xrange(node['count']):
dnode = self.fuel_web.get_devops_node_by_nailgun_node(
cluster_nodes[i])
self.assigned_slaves.remove(dnode.name)
nodes[dnode.name] = node['roles']
logger.info("Delete node {} with role {}".format(
dnode.name, node['roles']))
self.fuel_web.update_nodes(self.cluster_id, nodes, False, True)
@deferred_decorator([make_snapshot_if_step_fail])
@action
def scale_node(self):
"""Scale node in cluster"""
step_config = self.env_config['scale_nodes'][self.scale_step]
for node in step_config:
if node['action'] == 'add':
self._add_node([node])
elif node['action'] == 'delete':
self._del_node([node])
else:
logger.error("Unknow scale action: {}".format(node['action']))
self.scale_step += 1
from system_test import testcase
from system_test.tests import ActionTest
from system_test.actions import BaseActions
from system_test.actions import VMwareActions
@testcase(groups=['system_test',
'system_test.vcenter',
'system_test.vcenter.deploy_vcenter_dvs_run_ostf'])
class DeployWithVMware(VMwareActions):
class DeployWithVMware(ActionTest, BaseActions, VMwareActions):
"""Deploy cluster with vCenter and dvs plugin
Scenario:
@ -224,7 +60,7 @@ class DeployWithVMware(VMwareActions):
@testcase(groups=['system_test',
'system_test.vcenter',
'system_test.vcenter.scale_vcenter_dvs'])
class ScaleWithVMware(VMwareActions):
class ScaleWithVMware(ActionTest, BaseActions, VMwareActions):
"""Deploy and scale cluster with vCenter and dvs plugin
Scenario: