add set state test and aodh notifier test
Change-Id: I1fc72521af07bc1d4542bd55f813ee8b99690b4b
This commit is contained in:
parent
01cba4281d
commit
1ef4c31394
@ -16,8 +16,6 @@ import time
|
|||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from vitrage import clients
|
from vitrage import clients
|
||||||
from vitrage.common.constants import EntityCategory
|
|
||||||
from vitrage.common.constants import VertexProperties
|
|
||||||
|
|
||||||
from vitrage_tempest_tests.tests.api.base import BaseApiTest
|
from vitrage_tempest_tests.tests.api.base import BaseApiTest
|
||||||
|
|
||||||
@ -43,11 +41,8 @@ class BaseAlarmsTest(BaseApiTest):
|
|||||||
filtered_alarms_list = []
|
filtered_alarms_list = []
|
||||||
for item in alarms_list:
|
for item in alarms_list:
|
||||||
verification = 0
|
verification = 0
|
||||||
category = utils.uni2str(item[VertexProperties.CATEGORY])
|
|
||||||
for index in range(len(keys)):
|
for index in range(len(keys)):
|
||||||
key = utils.uni2str(item[keys[index]])
|
if utils.uni2str(item[keys[index]]) == values[index]:
|
||||||
if category == EntityCategory.ALARM \
|
|
||||||
and key == values[index]:
|
|
||||||
verification += 1
|
verification += 1
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
@ -35,7 +35,6 @@ from vitrageclient import client as v_client
|
|||||||
|
|
||||||
import vitrage_tempest_tests.tests.utils as utils
|
import vitrage_tempest_tests.tests.utils as utils
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -76,10 +75,9 @@ class BaseApiTest(base.BaseTestCase):
|
|||||||
|
|
||||||
def _get_host(self):
|
def _get_host(self):
|
||||||
topology = self.vitrage_client.topology.get()
|
topology = self.vitrage_client.topology.get()
|
||||||
for item in topology['nodes']:
|
host = filter(lambda item: item[VProps.TYPE] == NOVA_HOST_DATASOURCE,
|
||||||
if item[VProps.TYPE] == NOVA_HOST_DATASOURCE:
|
topology['nodes'])
|
||||||
return item
|
return host[0]
|
||||||
return None
|
|
||||||
|
|
||||||
def _create_instances(self, num_instances):
|
def _create_instances(self, num_instances):
|
||||||
flavors_list = self.nova_client.flavors.list()
|
flavors_list = self.nova_client.flavors.list()
|
||||||
@ -276,3 +274,7 @@ class BaseApiTest(base.BaseTestCase):
|
|||||||
num_edges,
|
num_edges,
|
||||||
'%s%s' % ('Num edges is incorrect for: %s',
|
'%s%s' % ('Num edges is incorrect for: %s',
|
||||||
entity[VProps.TYPE]))
|
entity[VProps.TYPE]))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_value(item, key):
|
||||||
|
return utils.uni2str(item[key])
|
||||||
|
@ -14,10 +14,16 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from vitrage.common.constants import VertexProperties
|
from vitrage.common.constants import VertexProperties as VProps
|
||||||
from vitrage.datasources import AODH_DATASOURCE
|
from vitrage.datasources import AODH_DATASOURCE
|
||||||
from vitrage.datasources import NOVA_HOST_DATASOURCE
|
from vitrage.datasources import NOVA_HOST_DATASOURCE
|
||||||
from vitrage.datasources import NOVA_INSTANCE_DATASOURCE
|
from vitrage.datasources import NOVA_INSTANCE_DATASOURCE
|
||||||
|
from vitrage.entity_graph.mappings.operational_alarm_severity \
|
||||||
|
import OperationalAlarmSeverity
|
||||||
|
from vitrage.entity_graph.mappings.operational_resource_state \
|
||||||
|
import OperationalResourceState
|
||||||
|
from vitrage.evaluator.actions.evaluator_event_transformer \
|
||||||
|
import VITRAGE_TYPE
|
||||||
|
|
||||||
from vitrage_tempest_tests.tests.api.alarms.base import BaseAlarmsTest
|
from vitrage_tempest_tests.tests.api.alarms.base import BaseAlarmsTest
|
||||||
import vitrage_tempest_tests.tests.utils as utils
|
import vitrage_tempest_tests.tests.utils as utils
|
||||||
@ -25,7 +31,6 @@ import vitrage_tempest_tests.tests.utils as utils
|
|||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
RCA_ALARM_NAME = 'rca_test_host_alarm'
|
RCA_ALARM_NAME = 'rca_test_host_alarm'
|
||||||
VITRAGE_ALARM_NAME = 'instance_deduce'
|
VITRAGE_ALARM_NAME = 'instance_deduce'
|
||||||
VITRAGE_DATASOURCE = 'vitrage'
|
|
||||||
|
|
||||||
|
|
||||||
class TestRca(BaseAlarmsTest):
|
class TestRca(BaseAlarmsTest):
|
||||||
@ -36,44 +41,137 @@ class TestRca(BaseAlarmsTest):
|
|||||||
super(TestRca, cls).setUpClass()
|
super(TestRca, cls).setUpClass()
|
||||||
|
|
||||||
def test_compare_cil_and_api(self):
|
def test_compare_cil_and_api(self):
|
||||||
|
"""compare_cil_and_api test
|
||||||
|
|
||||||
|
There test validate correctness of rca of created
|
||||||
|
aodh event alarms, and compare them with cli rca
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
vitrage_id = self._get_alarm_id(
|
instances = self._create_instances(num_instances=1)
|
||||||
resource_type=NOVA_INSTANCE_DATASOURCE,
|
if not instances:
|
||||||
|
LOG.error('Failed to create instance', False)
|
||||||
|
return False
|
||||||
|
|
||||||
|
instance_alarm = self._create_alarm(
|
||||||
|
resource_id=utils.uni2str(text=instances[0].id),
|
||||||
alarm_name='instance_rca_alarm', unic=True)
|
alarm_name='instance_rca_alarm', unic=True)
|
||||||
|
|
||||||
|
vitrage_id = self._get_value(
|
||||||
|
instance_alarm, VProps.VITRAGE_ID)
|
||||||
api_rca = self.vitrage_client.rca.get(alarm_id=vitrage_id)
|
api_rca = self.vitrage_client.rca.get(alarm_id=vitrage_id)
|
||||||
cli_rca = utils.run_vitrage_command(
|
cli_rca = utils.run_vitrage_command(
|
||||||
'vitrage rca show ' + vitrage_id, self.conf)
|
'vitrage rca show ' + vitrage_id, self.conf)
|
||||||
|
|
||||||
self.assertTrue(self._compare_rca(api_rca, cli_rca))
|
self.assertTrue(self._compare_rca(api_rca, cli_rca))
|
||||||
|
except Exception:
|
||||||
|
LOG.error('Got exception', False)
|
||||||
finally:
|
finally:
|
||||||
self._delete_ceilometer_alarms()
|
self._clean_all()
|
||||||
self._delete_instances()
|
|
||||||
|
|
||||||
def test_validate_rca(self):
|
def test_validate_rca(self):
|
||||||
|
"""validate_rca test
|
||||||
|
|
||||||
|
There tests validates correctness of rca of created aodh
|
||||||
|
event alarm and correctness of relationship between host alarm
|
||||||
|
to instance alarms (created by special template file),
|
||||||
|
source alarm - aodh alarm on host
|
||||||
|
target alarms - 2 instance alarms (caused 2 created instance)
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
vitrage_id = self._get_alarm_id(resource_type=NOVA_HOST_DATASOURCE,
|
self._create_instances(num_instances=2)
|
||||||
alarm_name=RCA_ALARM_NAME,
|
host_alarm = self._create_alarm(
|
||||||
unic=False)
|
resource_id=self._get_hostname(),
|
||||||
resources = self._create_instances(2)
|
alarm_name=RCA_ALARM_NAME,
|
||||||
api_rca = self.vitrage_client.rca.get(alarm_id=vitrage_id)
|
unic=False)
|
||||||
api_alarms = self.vitrage_client.alarms.list(vitrage_id=None)
|
api_rca = self.vitrage_client.rca.get(
|
||||||
|
alarm_id=self._get_value(host_alarm,
|
||||||
|
VProps.VITRAGE_ID))
|
||||||
|
|
||||||
self.assertTrue(self._validate_rca(rca=api_rca['nodes']))
|
self.assertTrue(self._validate_rca(rca=api_rca['nodes']))
|
||||||
self.assertTrue(self._validate_deduce_alarms(alarms=api_alarms,
|
self.assertTrue(self._validate_relationship(
|
||||||
resources=resources))
|
links=api_rca['links'],
|
||||||
|
alarms=api_rca['nodes']))
|
||||||
|
except Exception:
|
||||||
|
LOG.error('Got exception', False)
|
||||||
finally:
|
finally:
|
||||||
self._delete_ceilometer_alarms()
|
self._clean_all()
|
||||||
self._delete_instances()
|
|
||||||
|
|
||||||
def _get_alarm_id(self, resource_type, alarm_name, unic):
|
def test_validate_deduce_alarms(self):
|
||||||
if resource_type is NOVA_INSTANCE_DATASOURCE:
|
"""validate_deduce_alarms test
|
||||||
resource = self._create_instances(num_instances=1)
|
|
||||||
resource_id = utils.uni2str(resource[0].id)
|
There tests validates correctness of deduce alarms
|
||||||
else:
|
(created by special template file), and compare there
|
||||||
resource = self._get_host()
|
resource_id with created instances id
|
||||||
resource_id = utils.uni2str(resource[VertexProperties.ID])
|
"""
|
||||||
|
try:
|
||||||
|
instances = self._create_instances(num_instances=2)
|
||||||
|
self._create_alarm(
|
||||||
|
resource_id=self._get_hostname(),
|
||||||
|
alarm_name=RCA_ALARM_NAME)
|
||||||
|
api_alarms = self.vitrage_client.alarms.list(vitrage_id=None)
|
||||||
|
|
||||||
|
self.assertTrue(self._validate_deduce_alarms(
|
||||||
|
alarms=api_alarms,
|
||||||
|
instances=instances))
|
||||||
|
except Exception:
|
||||||
|
LOG.error('Got exception', False)
|
||||||
|
finally:
|
||||||
|
self._clean_all()
|
||||||
|
|
||||||
|
def test_validate_set_state(self):
|
||||||
|
"""validate_set_state test
|
||||||
|
|
||||||
|
There tests validates correctness of topology resource
|
||||||
|
state, after alarms creation (by special template file),
|
||||||
|
source state - ERROR
|
||||||
|
target state - SUBOPTIMAL (caused 2 created instance)
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
instances = self._create_instances(num_instances=2)
|
||||||
|
self._create_alarm(
|
||||||
|
resource_id=self._get_hostname(),
|
||||||
|
alarm_name=RCA_ALARM_NAME)
|
||||||
|
topology = self.vitrage_client.topology.get()
|
||||||
|
|
||||||
|
self.assertTrue(self._validate_set_state(
|
||||||
|
topology=topology['nodes'],
|
||||||
|
instances=instances))
|
||||||
|
except Exception:
|
||||||
|
LOG.error('Got exception', False)
|
||||||
|
finally:
|
||||||
|
self._clean_all()
|
||||||
|
|
||||||
|
def test_validate_notifier(self):
|
||||||
|
"""validate_notifier test
|
||||||
|
|
||||||
|
There tests validates work of aodh alarm notifier -
|
||||||
|
all created vitrage alarms appears in ceilometer
|
||||||
|
alarms-list.
|
||||||
|
IMPORTANT: enable notifiers=aodh in vitrage.conf file
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self._create_instances(num_instances=2)
|
||||||
|
self._create_alarm(
|
||||||
|
resource_id=self._get_hostname(),
|
||||||
|
alarm_name=RCA_ALARM_NAME)
|
||||||
|
vitrage_alarms = self.vitrage_client.alarms.list(vitrage_id=None)
|
||||||
|
ceilometer_alarms = self.ceilometer_client.alarms.list()
|
||||||
|
|
||||||
|
self.assertTrue(self._validate_notifier(
|
||||||
|
alarms=ceilometer_alarms,
|
||||||
|
vitrage_alarms=vitrage_alarms))
|
||||||
|
except Exception:
|
||||||
|
LOG.error('Got exception', False)
|
||||||
|
finally:
|
||||||
|
self._clean_all()
|
||||||
|
|
||||||
|
def _clean_all(self):
|
||||||
|
self._delete_instances()
|
||||||
|
self._delete_ceilometer_alarms()
|
||||||
|
|
||||||
|
def _create_alarm(self, resource_id, alarm_name, unic=False):
|
||||||
|
if not resource_id:
|
||||||
|
raise Exception("Can't create alarm with empty resource id")
|
||||||
|
|
||||||
self._create_ceilometer_alarm(resource_id=resource_id,
|
self._create_ceilometer_alarm(resource_id=resource_id,
|
||||||
name=alarm_name, unic=unic)
|
name=alarm_name, unic=unic)
|
||||||
@ -82,11 +180,11 @@ class TestRca(BaseAlarmsTest):
|
|||||||
expected_alarm = self._filter_alarms_by_parameter(
|
expected_alarm = self._filter_alarms_by_parameter(
|
||||||
list_alarms, ['resource_id', 'type'],
|
list_alarms, ['resource_id', 'type'],
|
||||||
[resource_id, AODH_DATASOURCE])
|
[resource_id, AODH_DATASOURCE])
|
||||||
return utils.uni2str(
|
if not expected_alarm:
|
||||||
expected_alarm[0][VertexProperties.VITRAGE_ID])
|
return None
|
||||||
|
return expected_alarm[0]
|
||||||
|
|
||||||
def _compare_rca(self, api_rca, cli_rca):
|
def _compare_rca(self, api_rca, cli_rca):
|
||||||
"""Validate alarm existence """
|
|
||||||
if not api_rca:
|
if not api_rca:
|
||||||
LOG.error("The rca taken from api is empty")
|
LOG.error("The rca taken from api is empty")
|
||||||
return False
|
return False
|
||||||
@ -104,7 +202,6 @@ class TestRca(BaseAlarmsTest):
|
|||||||
return sorted_cli_graph == sorted_api_graph
|
return sorted_cli_graph == sorted_api_graph
|
||||||
|
|
||||||
def _validate_rca(self, rca):
|
def _validate_rca(self, rca):
|
||||||
"""Validate alarm existence """
|
|
||||||
if not rca:
|
if not rca:
|
||||||
LOG.error("The alarms list is empty")
|
LOG.error("The alarms list is empty")
|
||||||
return False
|
return False
|
||||||
@ -117,13 +214,15 @@ class TestRca(BaseAlarmsTest):
|
|||||||
[AODH_DATASOURCE, RCA_ALARM_NAME])
|
[AODH_DATASOURCE, RCA_ALARM_NAME])
|
||||||
|
|
||||||
deduce_alarms = self._filter_alarms_by_parameter(
|
deduce_alarms = self._filter_alarms_by_parameter(
|
||||||
rca, ['type', 'name'],
|
rca, ['type', 'name', 'severity'],
|
||||||
[VITRAGE_DATASOURCE, VITRAGE_ALARM_NAME])
|
[VITRAGE_TYPE, VITRAGE_ALARM_NAME,
|
||||||
|
OperationalAlarmSeverity.WARNING])
|
||||||
|
|
||||||
return (len(resource_alarm) == 1 and
|
return (len(rca) == 3 and
|
||||||
|
len(resource_alarm) == 1 and
|
||||||
len(deduce_alarms) == 2)
|
len(deduce_alarms) == 2)
|
||||||
|
|
||||||
def _validate_deduce_alarms(self, alarms, resources):
|
def _validate_deduce_alarms(self, alarms, instances):
|
||||||
"""Validate alarm existence """
|
"""Validate alarm existence """
|
||||||
if not alarms:
|
if not alarms:
|
||||||
LOG.error("The alarms list is empty")
|
LOG.error("The alarms list is empty")
|
||||||
@ -135,25 +234,112 @@ class TestRca(BaseAlarmsTest):
|
|||||||
deduce_alarms_1 = self._filter_alarms_by_parameter(
|
deduce_alarms_1 = self._filter_alarms_by_parameter(
|
||||||
alarms,
|
alarms,
|
||||||
['type', 'name', 'resource_type', 'resource_id'],
|
['type', 'name', 'resource_type', 'resource_id'],
|
||||||
[VITRAGE_DATASOURCE, VITRAGE_ALARM_NAME,
|
[VITRAGE_TYPE, VITRAGE_ALARM_NAME,
|
||||||
NOVA_INSTANCE_DATASOURCE,
|
NOVA_INSTANCE_DATASOURCE,
|
||||||
utils.uni2str(resources[0].id)])
|
utils.uni2str(instances[0].id)])
|
||||||
|
|
||||||
deduce_alarms_2 = self._filter_alarms_by_parameter(
|
deduce_alarms_2 = self._filter_alarms_by_parameter(
|
||||||
alarms,
|
alarms,
|
||||||
['type', 'name', 'resource_type', 'resource_id'],
|
['type', 'name', 'resource_type', 'resource_id'],
|
||||||
[VITRAGE_DATASOURCE, VITRAGE_ALARM_NAME,
|
[VITRAGE_TYPE, VITRAGE_ALARM_NAME,
|
||||||
NOVA_INSTANCE_DATASOURCE,
|
NOVA_INSTANCE_DATASOURCE,
|
||||||
utils.uni2str(resources[1].id)])
|
utils.uni2str(instances[1].id)])
|
||||||
|
|
||||||
return (len(deduce_alarms_1) == 1 and
|
return (len(alarms) == 3 and
|
||||||
|
len(deduce_alarms_1) == 1 and
|
||||||
len(deduce_alarms_2) == 1)
|
len(deduce_alarms_2) == 1)
|
||||||
|
|
||||||
|
def _validate_relationship(self, links, alarms):
|
||||||
|
if not links:
|
||||||
|
LOG.error("The links list is empty")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not alarms:
|
||||||
|
LOG.error("The alarms list is empty")
|
||||||
|
return False
|
||||||
|
|
||||||
|
flag = True
|
||||||
|
for item in links:
|
||||||
|
source_alarm_name = self._get_value(
|
||||||
|
alarms[item['source']], VProps.NAME)
|
||||||
|
target_alarm_name = self._get_value(
|
||||||
|
alarms[item['target']], VProps.NAME)
|
||||||
|
if self._get_value(item, 'key') != 'causes' \
|
||||||
|
or self._get_value(item, 'relationship_type') != 'causes' \
|
||||||
|
or source_alarm_name != RCA_ALARM_NAME \
|
||||||
|
or target_alarm_name != VITRAGE_ALARM_NAME:
|
||||||
|
flag = False
|
||||||
|
|
||||||
|
return flag and len(alarms) == 3
|
||||||
|
|
||||||
|
def _validate_set_state(self, topology, instances):
|
||||||
|
if not topology:
|
||||||
|
LOG.error("The topology list is empty")
|
||||||
|
return False
|
||||||
|
|
||||||
|
host = self._filter_alarms_by_parameter(
|
||||||
|
topology,
|
||||||
|
[VProps.TYPE, VProps.ID, VProps.VITRAGE_STATE,
|
||||||
|
VProps.AGGREGATED_STATE],
|
||||||
|
[NOVA_HOST_DATASOURCE,
|
||||||
|
self._get_hostname(),
|
||||||
|
OperationalResourceState.ERROR,
|
||||||
|
OperationalResourceState.ERROR])
|
||||||
|
|
||||||
|
vm1 = self._filter_alarms_by_parameter(
|
||||||
|
topology,
|
||||||
|
[VProps.TYPE, VProps.ID, VProps.VITRAGE_STATE,
|
||||||
|
VProps.AGGREGATED_STATE],
|
||||||
|
[NOVA_INSTANCE_DATASOURCE,
|
||||||
|
utils.uni2str(instances[0].id),
|
||||||
|
OperationalResourceState.SUBOPTIMAL,
|
||||||
|
OperationalResourceState.SUBOPTIMAL])
|
||||||
|
|
||||||
|
vm2 = self._filter_alarms_by_parameter(
|
||||||
|
topology,
|
||||||
|
[VProps.TYPE, VProps.ID, VProps.VITRAGE_STATE,
|
||||||
|
VProps.AGGREGATED_STATE],
|
||||||
|
[NOVA_INSTANCE_DATASOURCE,
|
||||||
|
utils.uni2str(instances[1].id),
|
||||||
|
OperationalResourceState.SUBOPTIMAL,
|
||||||
|
OperationalResourceState.SUBOPTIMAL])
|
||||||
|
|
||||||
|
return len(host) == 1 and len(vm1) == 1 and len(vm2) == 1
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _validate_notifier(alarms, vitrage_alarms):
|
||||||
|
if not alarms:
|
||||||
|
LOG.error("The alarms list is empty")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not vitrage_alarms:
|
||||||
|
LOG.error("The vitrage alarms list is empty")
|
||||||
|
return False
|
||||||
|
|
||||||
|
validation = 0
|
||||||
|
for itemC in alarms:
|
||||||
|
vitrage_id = filter(
|
||||||
|
lambda item: item['field'] == VProps.VITRAGE_ID,
|
||||||
|
itemC.event_rule['query'])
|
||||||
|
for itemV in vitrage_alarms:
|
||||||
|
if not vitrage_id:
|
||||||
|
if itemC.name == itemV[VProps.NAME]:
|
||||||
|
validation += 1
|
||||||
|
break
|
||||||
|
elif vitrage_id[0]['value'] == itemV[VProps.VITRAGE_ID]:
|
||||||
|
validation += 1
|
||||||
|
break
|
||||||
|
return (len(vitrage_alarms) == validation
|
||||||
|
and len(alarms) == 3)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _clean_timestamps(alist):
|
def _clean_timestamps(alist):
|
||||||
try:
|
try:
|
||||||
del alist[5][1][0][VertexProperties.SAMPLE_TIMESTAMP]
|
del alist[5][1][0][VProps.SAMPLE_TIMESTAMP]
|
||||||
del alist[5][1][0][VertexProperties.UPDATE_TIMESTAMP]
|
del alist[5][1][0][VProps.UPDATE_TIMESTAMP]
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return alist
|
return alist
|
||||||
|
|
||||||
|
def _get_hostname(self):
|
||||||
|
return self._get_value(item=self._get_host(), key=VProps.ID)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user