Tempest refactoring

move code around so useful methods are in a common place.
create a clients singleton holding all required clients for testing.

Change-Id: I65d0a8b494ef760b9d14f132f5611cfefde03dc7
This commit is contained in:
Idan Hefetz 2017-11-05 10:40:18 +00:00
parent 6bd6c2e053
commit 6bdab3e626
27 changed files with 511 additions and 339 deletions

View File

@ -12,71 +12,23 @@
# License for the specific language governing permissions and limitations
# under the License.
import random
import time
from vitrage import os_clients
from vitrage_tempest_tests.tests.api.base import BaseApiTest
from vitrage_tempest_tests.tests.base import BaseVitrageTempest
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
TEMPLATES_RESOURCES_PATH = 'resources/templates/'
TEMPLATES_SOURCES_PATH = '/etc/vitrage/templates/'
class BaseAlarmsTest(BaseApiTest):
class BaseAlarmsTest(BaseVitrageTempest):
"""Topology test class for Vitrage API tests."""
@classmethod
def setUpClass(cls):
super(BaseAlarmsTest, cls).setUpClass()
cls.ceilometer_client = os_clients.ceilometer_client(cls.conf)
def _create_ceilometer_alarm(self, resource_id=None,
name=None, unic=True):
if not name:
name = '%s-%s' % ('test_', random.randrange(0, 100000, 1))
elif unic:
name = '%s-%s' % (name, random.randrange(0, 100000, 1))
aodh_request = self._aodh_request(resource_id=resource_id, name=name)
self.ceilometer_client.alarms.create(**aodh_request)
self._wait_for_status(20,
self._check_num_alarms,
num_alarms=1,
state='alarm')
time.sleep(25)
def _delete_ceilometer_alarms(self):
alarms = self.ceilometer_client.alarms.list()
for alarm in alarms:
self.ceilometer_client.alarms.delete(alarm.alarm_id)
self._wait_for_status(20,
self._check_num_alarms,
num_alarms=0)
time.sleep(120)
@staticmethod
def _aodh_request(resource_id=None, name=None):
query = []
if resource_id:
query = [
dict(
field=u'traits.resource_id',
type='',
op=u'eq',
value=resource_id)
]
return dict(
name=name,
description=u'test alarm',
event_rule=dict(query=query),
severity='low',
state='alarm',
type=u'event')
def _check_num_alarms(self, num_alarms=0, state=''):
if len(self.ceilometer_client.alarms.list()) != num_alarms:
if len(TempestClients.ceilometer().alarms.list()) != num_alarms:
return False
return all(alarm.state.upper() == state.upper()
for alarm in self.ceilometer_client.alarms.list())
for alarm in TempestClients.ceilometer().alarms.list())

View File

@ -19,7 +19,10 @@ from oslo_log import log as logging
from vitrage.common.constants import VertexProperties as VProps
from vitrage.datasources.aodh import AODH_DATASOURCE
from vitrage_tempest_tests.tests.api.alarms.base import BaseAlarmsTest
import vitrage_tempest_tests.tests.utils as utils
from vitrage_tempest_tests.tests.common import ceilometer_utils
from vitrage_tempest_tests.tests.common import nova_utils
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
from vitrage_tempest_tests.tests import utils
LOG = logging.getLogger(__name__)
@ -35,13 +38,14 @@ class TestAlarms(BaseAlarmsTest):
def test_compare_cli_vs_api_alarms(self):
"""Wrapper that returns a test graph."""
try:
instances = self._create_instances(num_instances=1)
instances = nova_utils.create_instances(num_instances=1)
self.assertNotEqual(len(instances), 0,
'The instances list is empty')
self._create_ceilometer_alarm(resource_id=instances[0].id,
name='tempest_aodh_test')
ceilometer_utils.create_ceilometer_alarm(
resource_id=instances[0].id,
name='tempest_aodh_test')
api_alarms = self.vitrage_client.alarm.list(vitrage_id=None)
api_alarms = TempestClients.vitrage().alarm.list(vitrage_id=None)
cli_alarms = utils.run_vitrage_command(
'vitrage alarm list', self.conf)
self._compare_alarms_lists(
@ -51,8 +55,8 @@ class TestAlarms(BaseAlarmsTest):
self._handle_exception(e)
raise
finally:
self._delete_ceilometer_alarms()
self._delete_instances()
ceilometer_utils.delete_all_ceilometer_alarms()
nova_utils.delete_all_instances()
def _compare_alarms_lists(self, api_alarms, cli_alarms,
resource_type, resource_id):

View File

@ -14,27 +14,20 @@
from datetime import datetime
from oslo_log import log as logging
from vitrage import keystone_client
from vitrage import service
from vitrage_tempest_tests.tests.api.base import BaseApiTest
from vitrageclient import client as v_client
from vitrage_tempest_tests.tests.base import BaseVitrageTempest
LOG = logging.getLogger(__name__)
DOWN = 'down'
UP = 'up'
class BaseTestEvents(BaseApiTest):
class BaseTestEvents(BaseVitrageTempest):
"""Test class for Vitrage event API"""
# noinspection PyPep8Naming
@classmethod
def setUpClass(cls):
cls.conf = service.prepare_service([])
cls.vitrage_client = \
v_client.Client('1', session=keystone_client.get_session(cls.conf))
super(BaseTestEvents, cls).setUpClass()
def _check_alarms(self):
api_alarms = self.vitrage_client.alarm.list(vitrage_id='all',

View File

@ -29,7 +29,10 @@ from vitrage.entity_graph.mappings.operational_resource_state \
from vitrage.evaluator.actions.evaluator_event_transformer \
import VITRAGE_DATASOURCE
from vitrage_tempest_tests.tests.api.alarms.base import BaseAlarmsTest
import vitrage_tempest_tests.tests.utils as utils
from vitrage_tempest_tests.tests.common import ceilometer_utils
from vitrage_tempest_tests.tests.common import nova_utils
from vitrage_tempest_tests.tests.common import vitrage_utils
from vitrage_tempest_tests.tests import utils
LOG = logging.getLogger(__name__)
RCA_ALARM_NAME = 'rca_test_host_alarm'
@ -43,12 +46,13 @@ class BaseRcaTest(BaseAlarmsTest):
super(BaseRcaTest, cls).setUpClass()
def _clean_all(self):
self._delete_instances()
self._delete_ceilometer_alarms()
nova_utils.delete_all_instances()
ceilometer_utils.delete_all_ceilometer_alarms()
def _create_alarm(self, resource_id, alarm_name, unic=False):
self._create_ceilometer_alarm(resource_id=resource_id,
name=alarm_name, unic=unic)
ceilometer_utils.create_ceilometer_alarm(resource_id=resource_id,
name=alarm_name,
unic=unic)
list_alarms = self.vitrage_client.alarm.list(vitrage_id=None)
expected_alarm = self._filter_list_by_pairs_parameters(
@ -186,7 +190,8 @@ class BaseRcaTest(BaseAlarmsTest):
self.assertEqual(3, len(alarms))
def _get_hostname(self):
return self._get_value(item=self._get_host(), key=VProps.ID)
host = vitrage_utils.get_first_host()
return self._get_value(item=host, key=VProps.ID)
@staticmethod
def _clean_timestamps(alist):

View File

@ -17,7 +17,9 @@ from oslo_log import log as logging
from vitrage.common.constants import VertexProperties as VProps
from vitrage_tempest_tests.tests.api.rca.base import BaseRcaTest
from vitrage_tempest_tests.tests.api.rca.base import RCA_ALARM_NAME
import vitrage_tempest_tests.tests.utils as utils
from vitrage_tempest_tests.tests.common import nova_utils
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
from vitrage_tempest_tests.tests import utils
LOG = logging.getLogger(__name__)
@ -37,7 +39,7 @@ class TestRca(BaseRcaTest):
aodh event alarms, and compare them with cli rca
"""
try:
instances = self._create_instances(num_instances=1)
instances = nova_utils.create_instances(num_instances=1)
self.assertNotEqual(len(instances), 0, 'Failed to create instance')
instance_alarm = self._create_alarm(
@ -68,7 +70,7 @@ class TestRca(BaseRcaTest):
target alarms - 2 instance alarms (caused 2 created instance)
"""
try:
self._create_instances(num_instances=2)
nova_utils.create_instances(num_instances=2)
host_alarm = self._create_alarm(
resource_id=self._get_hostname(),
alarm_name=RCA_ALARM_NAME,
@ -95,7 +97,7 @@ class TestRca(BaseRcaTest):
resource_id with created instances id
"""
try:
instances = self._create_instances(num_instances=2)
instances = nova_utils.create_instances(num_instances=2)
self._create_alarm(
resource_id=self._get_hostname(),
alarm_name=RCA_ALARM_NAME)
@ -119,7 +121,7 @@ class TestRca(BaseRcaTest):
target state - SUBOPTIMAL (caused 2 created instance)
"""
try:
instances = self._create_instances(num_instances=2)
instances = nova_utils.create_instances(num_instances=2)
self._create_alarm(
resource_id=self._get_hostname(),
alarm_name=RCA_ALARM_NAME)
@ -143,12 +145,13 @@ class TestRca(BaseRcaTest):
IMPORTANT: enable notifiers=aodh in vitrage.conf file
"""
try:
self._create_instances(num_instances=2)
nova_utils.create_instances(num_instances=2)
self._create_alarm(
resource_id=self._get_hostname(),
alarm_name=RCA_ALARM_NAME)
vitrage_alarms = self.vitrage_client.alarm.list(vitrage_id=None)
ceilometer_alarms = self.ceilometer_client.alarms.list()
vitrage_alarms = TempestClients.vitrage().alarm.list(
vitrage_id=None)
ceilometer_alarms = TempestClients.ceilometer().alarms.list()
self._validate_notifier(alarms=ceilometer_alarms,
vitrage_alarms=vitrage_alarms)

View File

@ -19,14 +19,14 @@ from oslo_log import log as logging
from vitrage.common.constants import VertexProperties as VProps
from vitrage.datasources import CINDER_VOLUME_DATASOURCE
from vitrage.datasources import NOVA_INSTANCE_DATASOURCE
from vitrage_tempest_tests.tests.api.base import BaseApiTest
import vitrage_tempest_tests.tests.utils as utils
from vitrage_tempest_tests.tests.base import BaseVitrageTempest
from vitrage_tempest_tests.tests.common import nova_utils
from vitrage_tempest_tests.tests import utils
LOG = logging.getLogger(__name__)
class TestResource(BaseApiTest):
class TestResource(BaseVitrageTempest):
"""Test class for Vitrage resource API tests."""
properties = (VProps.VITRAGE_ID,
@ -43,7 +43,7 @@ class TestResource(BaseApiTest):
def test_compare_cli_vs_api_resource_list(self):
"""resource list """
try:
instances = self._create_instances(num_instances=1)
instances = nova_utils.create_instances(num_instances=1)
self.assertNotEqual(len(instances), 0,
'The instances list is empty')
api_resources = self.vitrage_client.resource.list()
@ -55,7 +55,7 @@ class TestResource(BaseApiTest):
self._handle_exception(e)
raise
finally:
self._delete_instances()
nova_utils.delete_all_instances()
@utils.tempest_logger
def test_default_resource_list(self):
@ -64,7 +64,7 @@ class TestResource(BaseApiTest):
get the resources: cluster, zone, host and one instance
"""
try:
instances = self._create_instances(num_instances=1)
instances = nova_utils.create_instances(num_instances=1)
self.assertNotEqual(len(instances), 0,
'The instances list is empty')
resources = self.vitrage_client.resource.list()
@ -73,7 +73,7 @@ class TestResource(BaseApiTest):
self._handle_exception(e)
raise
finally:
self._delete_instances()
nova_utils.delete_all_instances()
@utils.tempest_logger
def test_resource_list_with_all_tenants(self):
@ -83,7 +83,7 @@ class TestResource(BaseApiTest):
cluster, zone, host and one instance(no other tenants)
"""
try:
instances = self._create_instances(num_instances=1)
instances = nova_utils.create_instances(num_instances=1)
self.assertNotEqual(len(instances), 0,
'The instances list is empty')
resources = self.vitrage_client.resource.list(all_tenants=True)
@ -92,7 +92,7 @@ class TestResource(BaseApiTest):
self._handle_exception(e)
raise
finally:
self._delete_instances()
nova_utils.delete_all_instances()
@utils.tempest_logger
def test_resource_list_with_existing_type(self):
@ -101,7 +101,7 @@ class TestResource(BaseApiTest):
get the resource: one instance
"""
try:
instances = self._create_instances(num_instances=1)
instances = nova_utils.create_instances(num_instances=1)
self.assertNotEqual(len(instances), 0,
'The instances list is empty')
resources = self.vitrage_client.resource.list(
@ -112,13 +112,13 @@ class TestResource(BaseApiTest):
self._handle_exception(e)
raise
finally:
self._delete_instances()
nova_utils.delete_all_instances()
@utils.tempest_logger
def test_resource_list_with_no_existing_type(self):
"""resource list with no existing type"""
try:
instances = self._create_instances(num_instances=1)
instances = nova_utils.create_instances(num_instances=1)
self.assertNotEqual(len(instances), 0,
'The instances list is empty')
resources = self.vitrage_client.resource.list(
@ -129,7 +129,7 @@ class TestResource(BaseApiTest):
self._handle_exception(e)
raise
finally:
self._delete_instances()
nova_utils.delete_all_instances()
def test_compare_resource_show(self):
"""resource_show test"""
@ -155,7 +155,7 @@ class TestResource(BaseApiTest):
self._handle_exception(e)
raise
finally:
self._delete_instances()
nova_utils.delete_all_instances()
def _compare_resources(self, api_resources, cli_resources):
self.assertNotEqual(len(api_resources), 0,

View File

@ -15,14 +15,13 @@ import json
from oslo_log import log as logging
from vitrage import os_clients
from vitrage_tempest_tests.tests.api.base import BaseApiTest
import vitrage_tempest_tests.tests.utils as utils
from vitrage_tempest_tests.tests.base import BaseVitrageTempest
from vitrage_tempest_tests.tests import utils
LOG = logging.getLogger(__name__)
class BaseTemplateTest(BaseApiTest):
class BaseTemplateTest(BaseVitrageTempest):
"""Template test class for Vitrage API tests."""
DEFAULT_PATH = '/etc/vitrage/templates/'
@ -40,7 +39,6 @@ class BaseTemplateTest(BaseApiTest):
@classmethod
def setUpClass(cls):
super(BaseTemplateTest, cls).setUpClass()
cls.ceilometer_client = os_clients.ceilometer_client(cls.conf)
def _compare_template_lists(self, api_templates, cli_templates):
self.assertNotEqual(len(api_templates), 0,

View File

@ -16,10 +16,12 @@ import json
import time
from vitrage.common.constants import VertexProperties as VProps
from vitrage_tempest_tests.tests.api.base import BaseApiTest
from vitrage_tempest_tests.tests.base import BaseVitrageTempest
from vitrage_tempest_tests.tests.common import cinder_utils
from vitrage_tempest_tests.tests.common import nova_utils
class BaseTopologyTest(BaseApiTest):
class BaseTopologyTest(BaseVitrageTempest):
"""Topology test class for Vitrage API tests."""
@classmethod
@ -43,21 +45,21 @@ class BaseTopologyTest(BaseApiTest):
def _create_entities(self, num_instances=0, num_volumes=0, end_sleep=3):
if num_instances > 0:
resources = self._create_instances(num_instances)
resources = nova_utils.create_instances(num_instances)
self.assertNotEqual(len(resources), 0, 'The instances list is empty')
if num_volumes > 0:
self._create_volume_and_attach('volume-1', 1,
resources[0].id,
'/tmp/vda')
cinder_utils.create_volume_and_attach('volume-1', 1,
resources[0].id,
'/tmp/vda')
# waiting until all the entities creation were processed by the
# entity graph processor
time.sleep(end_sleep)
def _delete_entities(self):
self._delete_volumes()
self._delete_instances()
cinder_utils.delete_all_volumes()
nova_utils.delete_all_instances()
# waiting until all the entities deletion were processed by the
# entity graph processor

View File

@ -12,12 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
import time
import traceback
from oslo_log import log as logging
from oslotest import base
from six.moves import filter
from vitrage.common.constants import EdgeProperties
from vitrage.common.constants import EntityCategory
@ -35,17 +33,15 @@ from vitrage.datasources.static_physical import SWITCH
from vitrage.graph.driver.networkx_graph import NXGraph
from vitrage.graph import Edge
from vitrage.graph import Vertex
from vitrage import keystone_client
from vitrage import os_clients
from vitrage import service
import vitrage_tempest_tests.tests.utils as utils
from vitrageclient import client as v_client
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
from vitrage_tempest_tests.tests import utils
LOG = logging.getLogger(__name__)
class BaseApiTest(base.BaseTestCase):
"""Base test class for Vitrage API tests."""
class BaseVitrageTempest(base.BaseTestCase):
"""Base test class for All Vitrage tests."""
NUM_VERTICES_PER_TYPE = 'num_vertices'
NUM_EDGES_PER_TYPE = 'num_edges_per_type'
@ -53,43 +49,18 @@ class BaseApiTest(base.BaseTestCase):
# noinspection PyPep8Naming
@classmethod
def setUpClass(cls):
super(BaseApiTest, cls).setUpClass()
super(BaseVitrageTempest, cls).setUpClass()
cls.conf = service.prepare_service([])
cls.vitrage_client = \
v_client.Client('1', session=keystone_client.get_session(cls.conf))
cls.nova_client = cls._create_client(os_clients.nova_client, cls.conf)
cls.cinder_client = cls._create_client(os_clients.cinder_client,
cls.conf)
cls.glance_client = cls._create_client(os_clients.glance_client,
cls.conf)
cls.neutron_client = cls._create_client(os_clients.neutron_client,
cls.conf)
cls.heat_client = cls._create_client(os_clients.heat_client, cls.conf)
TempestClients.class_init(cls.conf)
cls.vitrage_client = TempestClients.vitrage()
cls.num_default_networks = \
len(cls.neutron_client.list_networks()['networks'])
len(TempestClients.neutron().list_networks()['networks'])
cls.num_default_ports = \
len(cls.neutron_client.list_ports()['ports'])
len(TempestClients.neutron().list_ports()['ports'])
cls.num_default_entities = 3
cls.num_default_edges = 2
@staticmethod
def _create_client(client_func, conf):
count = 0
while count < 40:
LOG.info("wait_for_client - " + client_func.__name__)
client = client_func(conf)
if client:
return client
count += 1
time.sleep(5)
LOG.info("wait_for_client - False")
return None
@staticmethod
def _filter_list_by_pairs_parameters(origin_list,
keys, values):
@ -105,97 +76,20 @@ class BaseApiTest(base.BaseTestCase):
filtered_list.append(item)
return filtered_list
def _create_volume_and_attach(self, name, size, instance_id, mount_point):
volume = self.cinder_client.volumes.create(name=name,
size=size)
time.sleep(2)
self.cinder_client.volumes.attach(volume=volume,
instance_uuid=instance_id,
mountpoint=mount_point)
self._wait_for_status(30,
self._check_num_volumes,
num_volumes=1,
state='in-use')
time.sleep(2)
return volume
def _get_host(self):
topology = self.vitrage_client.topology.get(all_tenants=True)
host = filter(
lambda item: item[VProps.VITRAGE_TYPE] == NOVA_HOST_DATASOURCE,
topology['nodes'])
return next(host)
def _create_instances(self, num_instances, set_public_network=False):
kwargs = {}
flavors_list = self.nova_client.flavors.list()
images_list = self.glance_client.images.list()
if set_public_network:
public_net = self._get_public_network()
if public_net:
kwargs.update({"networks": [{'uuid': public_net['id']}]})
img = images_list.next()
resources = [self.nova_client.servers.create(
name='%s-%s' % ('vm', index),
flavor=flavors_list[0],
image=img,
**kwargs) for index in range(num_instances)]
self._wait_for_status(30,
self._check_num_instances,
num_instances=num_instances,
state='active')
time.sleep(2)
return resources
def _delete_instances(self):
instances = self.nova_client.servers.list()
for instance in instances:
try:
self.nova_client.servers.delete(instance)
except Exception:
pass
self._wait_for_status(30,
self._check_num_instances,
num_instances=0)
time.sleep(2)
def _delete_volumes(self):
volumes = self.cinder_client.volumes.list()
for volume in volumes:
try:
self.cinder_client.volumes.detach(volume)
self.cinder_client.volumes.force_delete(volume)
except Exception:
self.cinder_client.volumes.force_delete(volume)
self._wait_for_status(30,
self._check_num_volumes,
num_volumes=0)
time.sleep(2)
def _check_num_instances(self, num_instances=0, state=''):
if len(self.nova_client.servers.list()) != num_instances:
if len(TempestClients.nova().servers.list()) != num_instances:
return False
return all(instance.__dict__['status'].upper() == state.upper()
for instance in self.nova_client.servers.list())
for instance in TempestClients.nova().servers.list())
def _check_num_volumes(self, num_volumes=0, state=''):
if len(self.cinder_client.volumes.list()) != num_volumes:
if len(TempestClients.cinder().volumes.list()) != num_volumes:
return False
return all(volume.__dict__['status'].upper() == state.upper() and
len(volume.__dict__['attachments']) == 1
for volume in self.cinder_client.volumes.list())
for volume in TempestClients.cinder().volumes.list())
def _create_graph_from_graph_dictionary(self, api_graph):
self.assertIsNotNone(api_graph)
@ -236,17 +130,6 @@ class BaseApiTest(base.BaseTestCase):
return graph
@staticmethod
def _wait_for_status(max_waiting, func, **kwargs):
count = 0
while count < max_waiting:
if func(**kwargs):
return True
count += 1
time.sleep(2)
LOG.info("wait_for_status - False")
return False
def _entities_validation_data(self, **kwargs):
validation_data = []
@ -373,18 +256,8 @@ class BaseApiTest(base.BaseTestCase):
def _get_value(item, key):
return utils.uni2str(item[key])
def _get_public_network(self):
networks = self.neutron_client.list_networks()
public_nets = filter(
lambda item: self._get_value(item, VProps.NAME) == 'public',
networks['networks'])
try:
return next(public_nets)
except StopIteration:
return None
def _print_entity_graph(self):
api_graph = self.vitrage_client.topology.get(all_tenants=True)
api_graph = TempestClients.vitrage().topology.get(all_tenants=True)
graph = self._create_graph_from_graph_dictionary(api_graph)
LOG.info('Entity Graph: \n%s', graph.json_output_graph())

View File

@ -1,4 +1,4 @@
# Copyright 2016 - Nokia
# Copyright 2017 - Nokia
#
# 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

View File

@ -0,0 +1,54 @@
# Copyright 2017 - Nokia
#
# 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 random
import time
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
def create_ceilometer_alarm(resource_id=None, name=None, unic=True):
if not name:
name = '%s-%s' % ('test_', random.randrange(0, 100000, 1))
elif unic:
name = '%s-%s' % (name, random.randrange(0, 100000, 1))
aodh_request = _aodh_request(resource_id=resource_id, name=name)
TempestClients.ceilometer().alarms.create(**aodh_request)
time.sleep(45)
def delete_all_ceilometer_alarms():
alarms = TempestClients.ceilometer().alarms.list()
for alarm in alarms:
TempestClients.ceilometer().alarms.delete(alarm.alarm_id)
time.sleep(120)
def _aodh_request(resource_id=None, name=None):
query = []
if resource_id:
query = [
dict(
field=u'traits.resource_id',
type='',
op=u'eq',
value=resource_id)
]
return dict(
name=name,
description=u'test alarm',
event_rule=dict(query=query),
severity='low',
state='alarm',
type=u'event')

View File

@ -0,0 +1,49 @@
# Copyright 2017 - Nokia
#
# 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 time
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
from vitrage_tempest_tests.tests.utils import wait_for_status
def create_volume_and_attach(name, size, instance_id, mount_point):
volume = TempestClients.cinder().volumes.create(name=name,
size=size)
time.sleep(2)
TempestClients.cinder().volumes.attach(volume=volume,
instance_uuid=instance_id,
mountpoint=mount_point)
wait_for_status(30, _check_num_volumes, num_volumes=1, state='in-use')
time.sleep(2)
return volume
def delete_all_volumes():
volumes = TempestClients.cinder().volumes.list()
for volume in volumes:
try:
TempestClients.cinder().volumes.detach(volume)
TempestClients.cinder().volumes.force_delete(volume)
except Exception:
TempestClients.cinder().volumes.force_delete(volume)
wait_for_status(30, _check_num_volumes, num_volumes=0)
time.sleep(2)
def _check_num_volumes(num_volumes=0, state=''):
if len(TempestClients.cinder().volumes.list()) != num_volumes:
return False
return all(volume.__dict__['status'].upper() == state.upper() and
len(volume.__dict__['attachments']) == 1
for volume in TempestClients.cinder().volumes.list())

View File

@ -0,0 +1,18 @@
# Copyright 2017 - Nokia
#
# 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 vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
def get_first_image():
return TempestClients.glance().images.list().next()

View File

@ -0,0 +1,61 @@
# Copyright 2017 - Nokia
#
# 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 time
from heatclient.common import http
from heatclient.common import template_utils
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
from vitrage_tempest_tests.tests.utils import wait_for_status
def create_stacks(num_stacks, nested, template_file):
tpl_files, template = template_utils.process_template_path(
template_file,
object_request=http.authenticated_fetcher(TempestClients.heat()))
for i in range(num_stacks):
stack_name = 'stack_%s' % i + ('_nested' if nested else '')
TempestClients.heat().stacks.create(stack_name=stack_name,
template=template,
files=tpl_files,
parameters={})
wait_for_status(45,
_check_num_stacks,
num_stacks=num_stacks,
state='CREATE_COMPLETE')
time.sleep(2)
def delete_all_stacks():
stacks = TempestClients.heat().stacks.list()
for stack in stacks:
try:
TempestClients.heat().stacks.delete(stack.to_dict()['id'])
except Exception:
pass
wait_for_status(30, _check_num_stacks, num_stacks=0)
time.sleep(4)
def _check_num_stacks(num_stacks, state=''):
stacks_list = \
[stack.to_dict() for stack in TempestClients.heat().stacks.list()
if 'FAILED' not in stack.to_dict()['stack_status']]
if len(stacks_list) != num_stacks:
return False
return all(stack['stack_status'].upper() == state.upper()
for stack in stacks_list)

View File

@ -0,0 +1,23 @@
# Copyright 2017 - Nokia
#
# 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 vitrage.common.constants import VertexProperties as VProps
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
from vitrage_tempest_tests.tests.utils import uni2str
def get_public_network():
nets = TempestClients.neutron().list_networks()
return next(
(n for n in nets['networks'] if uni2str(n[VProps.NAME]) == 'public'),
None)

View File

@ -0,0 +1,62 @@
# Copyright 2017 - Nokia
#
# 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 time
from vitrage_tempest_tests.tests.common import glance_utils
from vitrage_tempest_tests.tests.common import neutron_utils
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
from vitrage_tempest_tests.tests.utils import wait_for_status
def create_instances(num_instances, set_public_network=False, name='vm'):
kwargs = {}
flavor = get_first_flavor()
image = glance_utils.get_first_image()
if set_public_network:
public_net = neutron_utils.get_public_network()
if public_net:
kwargs.update({"networks": [{'uuid': public_net['id']}]})
resources = [TempestClients.nova().servers.create(
name='%s-%s' % (name, index),
flavor=flavor,
image=image,
**kwargs) for index in range(num_instances)]
wait_for_status(30, _check_num_instances, num_instances=num_instances,
state='active')
time.sleep(2)
return resources
def delete_all_instances():
instances = TempestClients.nova().servers.list()
for instance in instances:
try:
TempestClients.nova().servers.delete(instance)
except Exception:
pass
wait_for_status(30, _check_num_instances, num_instances=0)
time.sleep(2)
def get_first_flavor():
return TempestClients.nova().flavors.list()[0]
def _check_num_instances(num_instances=0, state=''):
if len(TempestClients.nova().servers.list()) != num_instances:
return False
return all(instance.__dict__['status'].upper() == state.upper()
for instance in TempestClients.nova().servers.list())

View File

@ -0,0 +1,80 @@
# Copyright 2016 Nokia
#
# 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 vitrage import keystone_client
from vitrage import os_clients
from vitrageclient import client as vc
class TempestClients(object):
@classmethod
def class_init(cls, conf):
cls._conf = conf
cls._vitrage = None
cls._ceilometer = None
cls._nova = None
cls._cinder = None
cls._glance = None
cls._neutron = None
cls._heat = None
cls._mistral = None
@classmethod
def vitrage(cls):
if not cls._vitrage:
cls._vitrage = vc.Client(
'1', session=keystone_client.get_session(cls._conf))
return cls._vitrage
@classmethod
def ceilometer(cls):
if not cls._ceilometer:
cls._ceilometer = os_clients.ceilometer_client(cls._conf)
return cls._ceilometer
@classmethod
def nova(cls):
if not cls._nova:
cls._nova = os_clients.nova_client(cls._conf)
return cls._nova
@classmethod
def cinder(cls):
if not cls._cinder:
cls._cinder = os_clients.cinder_client(cls._conf)
return cls._cinder
@classmethod
def glance(cls):
if not cls._glance:
cls._glance = os_clients.glance_client(cls._conf)
return cls._glance
@classmethod
def neutron(cls):
if not cls._neutron:
cls._neutron = os_clients.neutron_client(cls._conf)
return cls._neutron
@classmethod
def heat(cls):
if not cls._heat:
cls._heat = os_clients.heat_client(cls._conf)
return cls._heat
@classmethod
def mistral(cls):
if not cls._mistral:
cls._mistral = os_clients.mistral_client(cls._conf)
return cls._mistral

View File

@ -0,0 +1,23 @@
# Copyright 2017 - Nokia
#
# 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 vitrage.common.constants import VertexProperties as VProps
from vitrage.datasources import NOVA_HOST_DATASOURCE
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
def get_first_host():
nodes = TempestClients.vitrage().topology.get(all_tenants=True)['nodes']
return next(
(n for n in nodes if n[VProps.VITRAGE_TYPE] == NOVA_HOST_DATASOURCE),
None)

View File

@ -16,6 +16,9 @@ from oslo_log import log as logging
from vitrage_tempest_tests.tests import utils
from vitrage_tempest_tests.tests.api.alarms.base import BaseAlarmsTest
from vitrage_tempest_tests.tests.common import ceilometer_utils
from vitrage_tempest_tests.tests.common import nova_utils
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
LOG = logging.getLogger(__name__)
@ -32,8 +35,9 @@ class TestAodhAlarm(BaseAlarmsTest):
def test_alarm_with_resource_id(self):
try:
# Action
self._create_instances(num_instances=self.NUM_INSTANCE)
self._create_ceilometer_alarm(self._find_instance_resource_id())
nova_utils.create_instances(num_instances=self.NUM_INSTANCE)
ceilometer_utils.create_ceilometer_alarm(
self._find_instance_resource_id())
# Calculate expected results
api_graph = self.vitrage_client.topology.get(all_tenants=True)
@ -60,14 +64,14 @@ class TestAodhAlarm(BaseAlarmsTest):
self._handle_exception(e)
raise
finally:
self._delete_ceilometer_alarms()
self._delete_instances()
ceilometer_utils.delete_all_ceilometer_alarms()
nova_utils.delete_all_instances()
@utils.tempest_logger
def test_alarm_without_resource_id(self):
try:
# Action
self._create_ceilometer_alarm()
ceilometer_utils.create_ceilometer_alarm()
# Calculate expected results
api_graph = self.vitrage_client.topology.get(all_tenants=True)
@ -90,8 +94,8 @@ class TestAodhAlarm(BaseAlarmsTest):
self._handle_exception(e)
raise
finally:
self._delete_ceilometer_alarms()
ceilometer_utils.delete_all_ceilometer_alarms()
def _find_instance_resource_id(self):
servers = self.nova_client.servers.list()
servers = TempestClients.nova().servers.list()
return servers[0].id

View File

@ -12,14 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
import time
from heatclient.common import http
from heatclient.common import template_utils
from oslo_log import log as logging
from vitrage_tempest_tests.tests import utils
from vitrage_tempest_tests.tests.api.topology.base import BaseTopologyTest
from vitrage_tempest_tests.tests.common import heat_utils
LOG = logging.getLogger(__name__)
@ -33,13 +30,16 @@ class TestHeatStack(BaseTopologyTest):
@utils.tempest_logger
def test_nested_heat_stack(self):
self._test_heat_stack(nested=True)
self._test_heat_stack(
nested=True,
template_file='/etc/vitrage/heat_nested_template.yaml')
@utils.tempest_logger
def test_heat_stack(self):
self._test_heat_stack(nested=False)
self._test_heat_stack(
nested=False, template_file='/etc/vitrage/heat_template.yaml')
def _test_heat_stack(self, nested):
def _test_heat_stack(self, nested, template_file):
"""heat stack test
This test validate correctness topology graph with heat stack module
@ -47,7 +47,7 @@ class TestHeatStack(BaseTopologyTest):
try:
# Action
self._create_stacks(self.NUM_STACKS, nested)
heat_utils.create_stacks(self.NUM_STACKS, nested, template_file)
# Calculate expected results
api_graph = self.vitrage_client.topology.get(all_tenants=True)
@ -77,50 +77,4 @@ class TestHeatStack(BaseTopologyTest):
self._handle_exception(e)
raise
finally:
self._delete_stacks()
def _create_stacks(self, num_stacks, nested):
template_file = 'heat_nested_template.yaml'\
if nested else 'heat_template.yaml'
tpl_files, template = template_utils.process_template_path(
'/etc/vitrage/' + template_file,
object_request=http.authenticated_fetcher(self.heat_client))
for i in range(num_stacks):
stack_name = 'stack_%s' % i + ('_nested' if nested else '')
self.heat_client.stacks.create(stack_name=stack_name,
template=template,
files=tpl_files,
parameters={})
self._wait_for_status(45,
self._check_num_stacks,
num_stacks=num_stacks,
state='CREATE_COMPLETE')
time.sleep(2)
def _delete_stacks(self):
stacks = self.heat_client.stacks.list()
for stack in stacks:
try:
self.heat_client.stacks.delete(stack.to_dict()['id'])
except Exception:
pass
self._wait_for_status(30,
self._check_num_stacks,
num_stacks=0)
time.sleep(4)
def _check_num_stacks(self, num_stacks, state=''):
stacks_list = \
[stack.to_dict() for stack in self.heat_client.stacks.list()
if 'FAILED' not in stack.to_dict()['stack_status']]
if len(stacks_list) != num_stacks:
return False
return all(stack['stack_status'].upper() == state.upper()
for stack in stacks_list)
heat_utils.delete_all_stacks()

View File

@ -16,6 +16,7 @@ from oslo_log import log as logging
from vitrage.common.constants import VertexProperties as VProps
from vitrage_tempest_tests.tests.api.topology.base import BaseTopologyTest
from vitrage_tempest_tests.tests.common import nova_utils
from vitrage_tempest_tests.tests import utils
LOG = logging.getLogger(__name__)
@ -37,8 +38,8 @@ class TestNeutron(BaseTopologyTest):
try:
# Action
self._create_instances(num_instances=self.NUM_INSTANCE,
set_public_network=True)
nova_utils.create_instances(num_instances=self.NUM_INSTANCE,
set_public_network=True)
# Calculate expected results
api_graph = self.vitrage_client.topology.get(all_tenants=True)
@ -67,7 +68,7 @@ class TestNeutron(BaseTopologyTest):
self._handle_exception(e)
raise
finally:
self._delete_instances()
nova_utils.delete_all_instances()
@staticmethod
def _get_network_name(instance, networks):

View File

@ -17,14 +17,13 @@ import socket
import time
from oslo_log import log as logging
from vitrage_tempest_tests.tests.api.base import BaseApiTest
from vitrage_tempest_tests.tests.base import BaseVitrageTempest
from vitrage_tempest_tests.tests import utils
LOG = logging.getLogger(__name__)
class TestStaticPhysical(BaseApiTest):
class TestStaticPhysical(BaseVitrageTempest):
NUM_SWITCH = 2
@classmethod

View File

@ -19,8 +19,10 @@ from vitrage import os_clients
from vitrage_tempest_tests.tests.api.event.base import BaseTestEvents
from vitrage_tempest_tests.tests.api.event.base import DOWN
from vitrage_tempest_tests.tests.api.event.base import UP
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
from vitrage_tempest_tests.tests.common import vitrage_utils
from vitrage_tempest_tests.tests import utils
from vitrage_tempest_tests.tests.utils import wait_for_answer
from vitrage_tempest_tests.tests.utils import wait_for_status
LOG = logging.getLogger(__name__)
@ -51,7 +53,7 @@ class TestMistralNotifier(BaseTestEvents):
@utils.tempest_logger
def test_execute_mistral(self):
hostname = self._get_host()['name']
hostname = vitrage_utils.get_first_host()['name']
workflows = self.mistral_client.workflows.list()
self.assertIsNotNone(workflows)
@ -61,7 +63,7 @@ class TestMistralNotifier(BaseTestEvents):
self.assertIsNotNone(executions)
num_executions = len(executions)
alarms = wait_for_answer(2, 0.5, self._check_alarms)
alarms = utils.wait_for_answer(2, 0.5, self._check_alarms)
self.assertIsNotNone(alarms)
num_alarms = len(alarms)
@ -81,16 +83,16 @@ class TestMistralNotifier(BaseTestEvents):
self._post_event(details)
# Wait for the alarm to be raised
self.assertTrue(
self._wait_for_status(10,
self._check_num_vitrage_alarms,
num_alarms=num_alarms + 1))
self.assertTrue(wait_for_status(
10,
self._check_num_vitrage_alarms,
num_alarms=num_alarms + 1))
# Wait for the Mistral workflow execution
self.assertTrue(
self._wait_for_status(20,
self._check_mistral_workflow_execution,
num_executions=num_executions + 1))
self.assertTrue(wait_for_status(
20,
self._check_mistral_workflow_execution,
num_executions=num_executions + 1))
except Exception as e:
self._handle_exception(e)
@ -113,14 +115,15 @@ class TestMistralNotifier(BaseTestEvents):
details = self._create_doctor_event_details(hostname, UP)
self._post_event(details)
self.assertTrue(
self._wait_for_status(10,
self._check_num_vitrage_alarms,
num_alarms=num_alarms))
self.assertTrue(wait_for_status(
10,
self._check_num_vitrage_alarms,
num_alarms=num_alarms))
def _check_num_vitrage_alarms(self, num_alarms):
if len(self.vitrage_client.alarm.list(vitrage_id='all',
all_tenants=True)) == num_alarms:
vitrage_alarms = TempestClients.vitrage().alarm.list(vitrage_id='all',
all_tenants=True)
if len(vitrage_alarms) == num_alarms:
return True
return False

View File

@ -159,3 +159,14 @@ def wait_for_answer(max_waiting, time_between_attempts, func, **kwargs):
return res
LOG.info("wait for answer- False")
return res
def wait_for_status(max_waiting, func, **kwargs):
count = 0
while count < max_waiting:
if func(**kwargs):
return True
count += 1
time.sleep(2)
LOG.info("wait_for_status - False")
return False