Merge "rca"
This commit is contained in:
commit
eafde06dbc
|
@ -0,0 +1,106 @@
|
||||||
|
# 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.
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
|
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
|
||||||
|
|
||||||
|
import vitrage_tempest_tests.tests.utils as utils
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
TEMPLATES_RESOURCES_PATH = 'resources/templates/'
|
||||||
|
TEMPLATES_SOURCES_PATH = '/etc/vitrage/templates/'
|
||||||
|
|
||||||
|
|
||||||
|
class BaseAlarmsTest(BaseApiTest):
|
||||||
|
"""Topology test class for Vitrage API tests."""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super(BaseAlarmsTest, cls).setUpClass()
|
||||||
|
cls.ceilometer_client = clients.ceilometer_client(cls.conf)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _filter_alarms_by_parameter(alarms_list,
|
||||||
|
keys, values):
|
||||||
|
filtered_alarms_list = []
|
||||||
|
for item in alarms_list:
|
||||||
|
verification = 0
|
||||||
|
category = utils.uni2str(item[VertexProperties.CATEGORY])
|
||||||
|
for index in range(len(keys)):
|
||||||
|
key = utils.uni2str(item[keys[index]])
|
||||||
|
if category == EntityCategory.ALARM \
|
||||||
|
and key == values[index]:
|
||||||
|
verification += 1
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
if verification == len(keys):
|
||||||
|
filtered_alarms_list.append(item)
|
||||||
|
return filtered_alarms_list
|
||||||
|
|
||||||
|
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)
|
||||||
|
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(25)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _aodh_request(resource_id=None, name=None):
|
||||||
|
query = []
|
||||||
|
if resource_id:
|
||||||
|
query = [
|
||||||
|
dict(
|
||||||
|
field=u'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:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return all(alarm.state.upper() == state.upper()
|
||||||
|
for alarm in self.ceilometer_client.alarms.list())
|
|
@ -14,80 +14,42 @@
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
from vitrage.datasources.aodh import AODH_DATASOURCE
|
||||||
|
|
||||||
from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE
|
from vitrage_tempest_tests.tests.api.alarms.base import BaseAlarmsTest
|
||||||
from vitrage.datasources.nova.instance import NOVA_INSTANCE_DATASOURCE
|
|
||||||
|
|
||||||
from vitrage_tempest_tests.tests.api.base import BaseApiTest
|
|
||||||
import vitrage_tempest_tests.tests.utils as utils
|
import vitrage_tempest_tests.tests.utils as utils
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class BaseAlarmsTest(BaseApiTest):
|
class TestAlarms(BaseAlarmsTest):
|
||||||
"""Alarms test class for Vitrage API tests."""
|
"""Alarms test class for Vitrage API tests."""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super(BaseAlarmsTest, cls).setUpClass()
|
super(TestAlarms, cls).setUpClass()
|
||||||
|
|
||||||
'''' Nova instances have alarms due to deduced alarm template: '''''
|
def test_compare_cli_vs_api_alarms(self):
|
||||||
'''' nova_alarm_for_every_host.yaml '''''
|
|
||||||
'''' nova_alarm_for_every_instance.yaml '''''
|
|
||||||
'''' Nagios alarm template is nagios_alarm.yaml '''''
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def copy_alarms_templates_files():
|
|
||||||
utils.run_from_terminal(
|
|
||||||
"cp " +
|
|
||||||
"vitrage_tempest_tests/tests/resources/templates/"
|
|
||||||
+ "*_alarm* /etc/vitrage/templates/.")
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def delete_alarms_templates_files():
|
|
||||||
utils.run_from_terminal(
|
|
||||||
"rm /etc/vitrage/templates/*_alarm*")
|
|
||||||
|
|
||||||
def test_compare_alarms(self):
|
|
||||||
"""Wrapper that returns a test graph."""
|
"""Wrapper that returns a test graph."""
|
||||||
self._create_instances(num_instances=3)
|
try:
|
||||||
api_alarms = self.vitrage_client.alarms.list(vitrage_id=None)
|
resources = self._create_instances(num_instances=1)
|
||||||
cli_alarms = utils.run_vitrage_command('vitrage alarms list',
|
self._create_ceilometer_alarm(resource_id=resources[0].id,
|
||||||
self.conf)
|
name='tempest_aodh_test')
|
||||||
self.assertEqual(True,
|
|
||||||
self._compare_alarms_lists(api_alarms, cli_alarms))
|
|
||||||
self._delete_instances()
|
|
||||||
|
|
||||||
def test_nova_alarms(self):
|
api_alarms = self.vitrage_client.alarms.list(vitrage_id=None)
|
||||||
"""Wrapper that returns test nova alarms."""
|
cli_alarms = utils.run_vitrage_command(
|
||||||
self._create_instances(num_instances=4)
|
'vitrage alarms list', self.conf)
|
||||||
resources = self.nova_client.servers.list()
|
self.assertTrue(self._compare_alarms_lists(
|
||||||
|
api_alarms, cli_alarms, AODH_DATASOURCE,
|
||||||
|
utils.uni2str(resources[0].id)))
|
||||||
|
|
||||||
alarms = self.vitrage_client.alarms.list(vitrage_id=None)
|
finally:
|
||||||
nova_alarms = self._filter_alarms_by_resource_type(
|
self._delete_ceilometer_alarms()
|
||||||
alarms, NOVA_INSTANCE_DATASOURCE)
|
self._delete_instances()
|
||||||
self.assertEqual(True, self._validate_alarms_correctness(nova_alarms,
|
|
||||||
resources))
|
|
||||||
self._delete_instances()
|
|
||||||
|
|
||||||
# def test_nagios_alarms(self):
|
def _compare_alarms_lists(self, api_alarms, cli_alarms,
|
||||||
# """Wrapper that returns test nagios alarms."""
|
resource_type, resource_id):
|
||||||
# alarms = self.vitrage_client.alarms.list()
|
|
||||||
# nagios_alarms = self._filter_alarms_by_resource_type(alarms,
|
|
||||||
# 'nagios')
|
|
||||||
# self.assertEqual(True, self._validate_alarms_correctness(
|
|
||||||
# nagios_alarms, 'nagios'))
|
|
||||||
|
|
||||||
# def test_aodh_alarms(self):
|
|
||||||
# """Wrapper that returns test aodh alarms."""
|
|
||||||
# # self.create_alarms_per_component('aodh')
|
|
||||||
# alarms = self.vitrage_client.alarms.list()
|
|
||||||
# aodh_alarms = self._filter_alarms_by_resource_type(alarms,
|
|
||||||
# 'aodh')
|
|
||||||
# self.assertEqual(True, self._validate_alarms_correctness(
|
|
||||||
# aodh_alarms, 'aodh'))
|
|
||||||
|
|
||||||
def _compare_alarms_lists(self, api_alarms, cli_alarms):
|
|
||||||
"""Validate alarm existence """
|
"""Validate alarm existence """
|
||||||
if not api_alarms:
|
if not api_alarms:
|
||||||
LOG.error("The alarms list taken from api is empty")
|
LOG.error("The alarms list taken from api is empty")
|
||||||
|
@ -100,48 +62,15 @@ class BaseAlarmsTest(BaseApiTest):
|
||||||
LOG.debug("The alarms list taken by api is : %s",
|
LOG.debug("The alarms list taken by api is : %s",
|
||||||
json.dumps(api_alarms))
|
json.dumps(api_alarms))
|
||||||
|
|
||||||
cli_items = cli_alarms.count('vitrage')
|
cli_items = cli_alarms.splitlines()
|
||||||
nova_instance_alarms = \
|
|
||||||
self._filter_alarms_by_resource_type(api_alarms,
|
|
||||||
NOVA_INSTANCE_DATASOURCE)
|
|
||||||
nova_instances = cli_alarms.count(NOVA_INSTANCE_DATASOURCE)
|
|
||||||
nova_host_alarms = \
|
|
||||||
self._filter_alarms_by_resource_type(api_alarms,
|
|
||||||
NOVA_HOST_DATASOURCE)
|
|
||||||
nova_hosts = cli_alarms.count(NOVA_HOST_DATASOURCE)
|
|
||||||
return (cli_items == len(api_alarms) and
|
|
||||||
nova_instances == len(nova_instance_alarms) and
|
|
||||||
nova_hosts == len(nova_host_alarms))
|
|
||||||
|
|
||||||
@staticmethod
|
api_by_type = self._filter_alarms_by_parameter(
|
||||||
def _validate_alarms_correctness(alarms, resources):
|
api_alarms, ['type'], [resource_type])
|
||||||
"""Validate alarm existence """
|
cli_by_type = cli_alarms.count(' ' + resource_type + ' ')
|
||||||
if not alarms:
|
|
||||||
LOG.error("The alarms list is empty")
|
|
||||||
return False
|
|
||||||
if not resources:
|
|
||||||
LOG.error("The resources list is empty")
|
|
||||||
return False
|
|
||||||
|
|
||||||
count = 0
|
api_by_id = self._filter_alarms_by_parameter(
|
||||||
for resource in resources:
|
api_alarms, ['resource_id'], [resource_id])
|
||||||
LOG.info("______________________")
|
cli_by_id = cli_alarms.count(resource_id)
|
||||||
LOG.info("The resource id is %s", resource.id)
|
return (len(cli_items) - 4 == len(api_alarms) and
|
||||||
for item in alarms:
|
cli_by_type == len(api_by_type) and
|
||||||
LOG.info("The alarms resource id is %s", item["resource_id"])
|
cli_by_id == len(api_by_id))
|
||||||
if item["resource_id"] == resource.id:
|
|
||||||
count += 1
|
|
||||||
|
|
||||||
LOG.info("The resources list size is %s", len(resources))
|
|
||||||
LOG.info("The common items list size is %s", count)
|
|
||||||
return count == len(resources)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _filter_alarms_by_resource_type(alarms_list, alarm_type):
|
|
||||||
filtered_alarms_list = []
|
|
||||||
for item in alarms_list:
|
|
||||||
if item["category"] == "ALARM" \
|
|
||||||
and item["resource_type"] == alarm_type:
|
|
||||||
filtered_alarms_list.append(item)
|
|
||||||
|
|
||||||
return filtered_alarms_list
|
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
@ -32,9 +31,11 @@ from vitrage.graph import NXGraph
|
||||||
from vitrage.graph import Vertex
|
from vitrage.graph import Vertex
|
||||||
from vitrage import keystone_client
|
from vitrage import keystone_client
|
||||||
from vitrage_tempest_tests.tests import OPTS
|
from vitrage_tempest_tests.tests import OPTS
|
||||||
import vitrage_tempest_tests.tests.utils as utils
|
|
||||||
from vitrageclient import client as v_client
|
from vitrageclient import client as v_client
|
||||||
|
|
||||||
|
import vitrage_tempest_tests.tests.utils as utils
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,6 +51,7 @@ class BaseApiTest(base.BaseTestCase):
|
||||||
super(BaseApiTest, cls).setUpClass()
|
super(BaseApiTest, cls).setUpClass()
|
||||||
cls.conf = utils.get_conf()
|
cls.conf = utils.get_conf()
|
||||||
cls.conf.register_opts(list(OPTS), group='keystone_authtoken')
|
cls.conf.register_opts(list(OPTS), group='keystone_authtoken')
|
||||||
|
|
||||||
cls.vitrage_client = \
|
cls.vitrage_client = \
|
||||||
v_client.Client('1', session=keystone_client.get_session(cls.conf))
|
v_client.Client('1', session=keystone_client.get_session(cls.conf))
|
||||||
cls.nova_client = clients.nova_client(cls.conf)
|
cls.nova_client = clients.nova_client(cls.conf)
|
||||||
|
@ -72,6 +74,13 @@ class BaseApiTest(base.BaseTestCase):
|
||||||
|
|
||||||
return volume
|
return volume
|
||||||
|
|
||||||
|
def _get_host(self):
|
||||||
|
topology = self.vitrage_client.topology.get()
|
||||||
|
for item in topology['nodes']:
|
||||||
|
if item[VProps.TYPE] == NOVA_HOST_DATASOURCE:
|
||||||
|
return item
|
||||||
|
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()
|
||||||
images_list = self.nova_client.images.list()
|
images_list = self.nova_client.images.list()
|
||||||
|
|
|
@ -11,19 +11,15 @@
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import random
|
|
||||||
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_tempest_tests.tests.api.base import BaseApiTest
|
from vitrage_tempest_tests.tests.api.alarms.base import BaseAlarmsTest
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class TestAodhAlarm(BaseApiTest):
|
class TestAodhAlarm(BaseAlarmsTest):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
@ -63,51 +59,6 @@ class TestAodhAlarm(BaseApiTest):
|
||||||
finally:
|
finally:
|
||||||
self._delete_ceilometer_alarms()
|
self._delete_ceilometer_alarms()
|
||||||
|
|
||||||
def _create_ceilometer_alarm(self, resource_id=None):
|
|
||||||
aodh_request = self._aodh_request(resource_id=resource_id)
|
|
||||||
self.ceilometer_client.alarms.create(**aodh_request)
|
|
||||||
self._wait_for_status(30,
|
|
||||||
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(30,
|
|
||||||
self._check_num_alarms,
|
|
||||||
num_alarms=0)
|
|
||||||
time.sleep(25)
|
|
||||||
|
|
||||||
def _check_num_alarms(self, num_alarms=0, state=''):
|
|
||||||
if len(self.ceilometer_client.alarms.list()) != num_alarms:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return all(alarm.__dict__['state'].upper() == state.upper()
|
|
||||||
for alarm in self.ceilometer_client.alarms.list())
|
|
||||||
|
|
||||||
def _aodh_request(self, resource_id=None):
|
|
||||||
query = []
|
|
||||||
if resource_id:
|
|
||||||
query = [
|
|
||||||
dict(
|
|
||||||
field=u'resource_id',
|
|
||||||
type='',
|
|
||||||
op=u'eq',
|
|
||||||
value=resource_id)
|
|
||||||
]
|
|
||||||
|
|
||||||
random_name = '%s-%s' % ('test', random.randrange(0, 100000, 1))
|
|
||||||
return dict(
|
|
||||||
name=random_name,
|
|
||||||
description=u'test alarm',
|
|
||||||
event_rule=dict(query=query),
|
|
||||||
severity='low',
|
|
||||||
state='alarm', # ok/alarm/insufficient data
|
|
||||||
type=u'event')
|
|
||||||
|
|
||||||
def _find_instance_resource_id(self):
|
def _find_instance_resource_id(self):
|
||||||
servers = self.nova_client.servers.list()
|
servers = self.nova_client.servers.list()
|
||||||
return servers[0].id
|
return servers[0].id
|
||||||
|
|
|
@ -11,5 +11,149 @@
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
import json
|
||||||
|
|
||||||
__author__ = 'stack'
|
from oslo_log import log as logging
|
||||||
|
from vitrage.common.constants import VertexProperties
|
||||||
|
from vitrage.datasources import AODH_DATASOURCE
|
||||||
|
from vitrage.datasources import NOVA_HOST_DATASOURCE
|
||||||
|
from vitrage.datasources import NOVA_INSTANCE_DATASOURCE
|
||||||
|
|
||||||
|
from vitrage_tempest_tests.tests.api.alarms.base import BaseAlarmsTest
|
||||||
|
import vitrage_tempest_tests.tests.utils as utils
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
RCA_ALARM_NAME = 'rca_test_host_alarm'
|
||||||
|
VITRAGE_ALARM_NAME = 'instance_deduce'
|
||||||
|
VITRAGE_DATASOURCE = 'vitrage'
|
||||||
|
|
||||||
|
|
||||||
|
class TestRca(BaseAlarmsTest):
|
||||||
|
"""RCA test class for Vitrage API tests."""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super(TestRca, cls).setUpClass()
|
||||||
|
|
||||||
|
def test_compare_cil_and_api(self):
|
||||||
|
try:
|
||||||
|
vitrage_id = self._get_alarm_id(
|
||||||
|
resource_type=NOVA_INSTANCE_DATASOURCE,
|
||||||
|
alarm_name='instance_rca_alarm', unic=True)
|
||||||
|
|
||||||
|
api_rca = self.vitrage_client.rca.get(alarm_id=vitrage_id)
|
||||||
|
cli_rca = utils.run_vitrage_command(
|
||||||
|
'vitrage rca show ' + vitrage_id, self.conf)
|
||||||
|
|
||||||
|
self.assertTrue(self._compare_rca(api_rca, cli_rca))
|
||||||
|
|
||||||
|
finally:
|
||||||
|
self._delete_ceilometer_alarms()
|
||||||
|
self._delete_instances()
|
||||||
|
|
||||||
|
def test_validate_rca(self):
|
||||||
|
try:
|
||||||
|
vitrage_id = self._get_alarm_id(resource_type=NOVA_HOST_DATASOURCE,
|
||||||
|
alarm_name=RCA_ALARM_NAME,
|
||||||
|
unic=False)
|
||||||
|
resources = self._create_instances(2)
|
||||||
|
api_rca = self.vitrage_client.rca.get(alarm_id=vitrage_id)
|
||||||
|
api_alarms = self.vitrage_client.alarms.list(vitrage_id=None)
|
||||||
|
|
||||||
|
self.assertTrue(self._validate_rca(rca=api_rca['nodes']))
|
||||||
|
self.assertTrue(self._validate_deduce_alarms(alarms=api_alarms,
|
||||||
|
resources=resources))
|
||||||
|
finally:
|
||||||
|
self._delete_ceilometer_alarms()
|
||||||
|
self._delete_instances()
|
||||||
|
|
||||||
|
def _get_alarm_id(self, resource_type, alarm_name, unic):
|
||||||
|
if resource_type is NOVA_INSTANCE_DATASOURCE:
|
||||||
|
resource = self._create_instances(num_instances=1)
|
||||||
|
resource_id = utils.uni2str(resource[0].id)
|
||||||
|
else:
|
||||||
|
resource = self._get_host()
|
||||||
|
resource_id = utils.uni2str(resource[VertexProperties.ID])
|
||||||
|
|
||||||
|
self._create_ceilometer_alarm(resource_id=resource_id,
|
||||||
|
name=alarm_name, unic=unic)
|
||||||
|
|
||||||
|
list_alarms = self.vitrage_client.alarms.list(vitrage_id=None)
|
||||||
|
expected_alarm = self._filter_alarms_by_parameter(
|
||||||
|
list_alarms, ['resource_id', 'type'],
|
||||||
|
[resource_id, AODH_DATASOURCE])
|
||||||
|
return utils.uni2str(
|
||||||
|
expected_alarm[0][VertexProperties.VITRAGE_ID])
|
||||||
|
|
||||||
|
def _compare_rca(self, api_rca, cli_rca):
|
||||||
|
"""Validate alarm existence """
|
||||||
|
if not api_rca:
|
||||||
|
LOG.error("The rca taken from api is empty")
|
||||||
|
return False
|
||||||
|
if cli_rca is None:
|
||||||
|
LOG.error("The rca taken from cli is empty")
|
||||||
|
return False
|
||||||
|
|
||||||
|
LOG.debug("The rca taken from cli is : %s", cli_rca)
|
||||||
|
LOG.debug("The rca taken by api is : %s",
|
||||||
|
json.dumps(api_rca))
|
||||||
|
|
||||||
|
parsed_rca = json.loads(cli_rca)
|
||||||
|
sorted_cli_graph = self._clean_timestamps(sorted(parsed_rca.items()))
|
||||||
|
sorted_api_graph = self._clean_timestamps(sorted(api_rca.items()))
|
||||||
|
return sorted_cli_graph == sorted_api_graph
|
||||||
|
|
||||||
|
def _validate_rca(self, rca):
|
||||||
|
"""Validate alarm existence """
|
||||||
|
if not rca:
|
||||||
|
LOG.error("The alarms list is empty")
|
||||||
|
return False
|
||||||
|
|
||||||
|
LOG.debug("The rca alarms list is : %s",
|
||||||
|
json.dumps(rca))
|
||||||
|
|
||||||
|
resource_alarm = self._filter_alarms_by_parameter(
|
||||||
|
rca, ['type', 'name'],
|
||||||
|
[AODH_DATASOURCE, RCA_ALARM_NAME])
|
||||||
|
|
||||||
|
deduce_alarms = self._filter_alarms_by_parameter(
|
||||||
|
rca, ['type', 'name'],
|
||||||
|
[VITRAGE_DATASOURCE, VITRAGE_ALARM_NAME])
|
||||||
|
|
||||||
|
return (len(resource_alarm) == 1 and
|
||||||
|
len(deduce_alarms) == 2)
|
||||||
|
|
||||||
|
def _validate_deduce_alarms(self, alarms, resources):
|
||||||
|
"""Validate alarm existence """
|
||||||
|
if not alarms:
|
||||||
|
LOG.error("The alarms list is empty")
|
||||||
|
return False
|
||||||
|
|
||||||
|
LOG.debug("The alarms list is : %s",
|
||||||
|
json.dumps(alarms))
|
||||||
|
|
||||||
|
deduce_alarms_1 = self._filter_alarms_by_parameter(
|
||||||
|
alarms,
|
||||||
|
['type', 'name', 'resource_type', 'resource_id'],
|
||||||
|
[VITRAGE_DATASOURCE, VITRAGE_ALARM_NAME,
|
||||||
|
NOVA_INSTANCE_DATASOURCE,
|
||||||
|
utils.uni2str(resources[0].id)])
|
||||||
|
|
||||||
|
deduce_alarms_2 = self._filter_alarms_by_parameter(
|
||||||
|
alarms,
|
||||||
|
['type', 'name', 'resource_type', 'resource_id'],
|
||||||
|
[VITRAGE_DATASOURCE, VITRAGE_ALARM_NAME,
|
||||||
|
NOVA_INSTANCE_DATASOURCE,
|
||||||
|
utils.uni2str(resources[1].id)])
|
||||||
|
|
||||||
|
return (len(deduce_alarms_1) == 1 and
|
||||||
|
len(deduce_alarms_2) == 1)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _clean_timestamps(alist):
|
||||||
|
try:
|
||||||
|
del alist[5][1][0][VertexProperties.SAMPLE_TIMESTAMP]
|
||||||
|
del alist[5][1][0][VertexProperties.UPDATE_TIMESTAMP]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return alist
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
metadata:
|
||||||
|
id: host_aodh_alarm
|
||||||
|
definitions:
|
||||||
|
entities:
|
||||||
|
- entity:
|
||||||
|
category: ALARM
|
||||||
|
type: aodh
|
||||||
|
name: 'rca_test_host_alarm'
|
||||||
|
template_id: host_alarm
|
||||||
|
- entity:
|
||||||
|
category: RESOURCE
|
||||||
|
type: nova.host
|
||||||
|
template_id: host
|
||||||
|
- entity:
|
||||||
|
category: RESOURCE
|
||||||
|
type: nova.instance
|
||||||
|
template_id: instance
|
||||||
|
- entity:
|
||||||
|
category: ALARM
|
||||||
|
type: vitrage
|
||||||
|
name: instance_deduce
|
||||||
|
template_id: instance_alarm
|
||||||
|
relationships:
|
||||||
|
- relationship:
|
||||||
|
source: host_alarm
|
||||||
|
target: host
|
||||||
|
relationship_type: on
|
||||||
|
template_id : alarm_on_host
|
||||||
|
- relationship:
|
||||||
|
source: instance_alarm
|
||||||
|
target: instance
|
||||||
|
relationship_type: on
|
||||||
|
template_id : alarm_on_instance
|
||||||
|
- relationship:
|
||||||
|
source: host
|
||||||
|
target: instance
|
||||||
|
relationship_type: contains
|
||||||
|
template_id: host_contains_instance
|
||||||
|
scenarios:
|
||||||
|
- scenario:
|
||||||
|
condition: alarm_on_host
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: set_state
|
||||||
|
action_target:
|
||||||
|
target: host
|
||||||
|
properties:
|
||||||
|
state: ERROR
|
||||||
|
- scenario:
|
||||||
|
condition: alarm_on_host and host_contains_instance
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: raise_alarm
|
||||||
|
action_target:
|
||||||
|
target: instance
|
||||||
|
properties:
|
||||||
|
alarm_name: instance_deduce
|
||||||
|
severity: WARNING
|
||||||
|
- action:
|
||||||
|
action_type: set_state
|
||||||
|
action_target:
|
||||||
|
target: instance
|
||||||
|
properties:
|
||||||
|
state: SUBOPTIMAL
|
||||||
|
- scenario:
|
||||||
|
condition: alarm_on_host and host_contains_instance and alarm_on_instance
|
||||||
|
actions:
|
||||||
|
- action:
|
||||||
|
action_type: add_causal_relationship
|
||||||
|
action_target:
|
||||||
|
source: host_alarm
|
||||||
|
target: instance_alarm
|
|
@ -1,20 +0,0 @@
|
||||||
metadata:
|
|
||||||
id: free alarms for hosts
|
|
||||||
definitions:
|
|
||||||
entities:
|
|
||||||
- entity:
|
|
||||||
category: RESOURCE
|
|
||||||
type: nova.host
|
|
||||||
template_id: host
|
|
||||||
scenarios:
|
|
||||||
- scenario:
|
|
||||||
condition: host
|
|
||||||
actions:
|
|
||||||
- action:
|
|
||||||
action_type: raise_alarm
|
|
||||||
action_target:
|
|
||||||
target: host
|
|
||||||
properties:
|
|
||||||
alarm_name: host_alarm
|
|
||||||
severity: so_so
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
metadata:
|
|
||||||
id: free alarms for instances
|
|
||||||
definitions:
|
|
||||||
entities:
|
|
||||||
- entity:
|
|
||||||
category: RESOURCE
|
|
||||||
type: nova.instance
|
|
||||||
template_id: vm
|
|
||||||
scenarios:
|
|
||||||
- scenario:
|
|
||||||
condition: vm
|
|
||||||
actions:
|
|
||||||
- action:
|
|
||||||
action_type: raise_alarm
|
|
||||||
action_target:
|
|
||||||
target: vm
|
|
||||||
properties:
|
|
||||||
alarm_name: vm_alarm
|
|
||||||
severity: so_so
|
|
||||||
|
|
|
@ -67,14 +67,18 @@ def run_vitrage_command(command, conf):
|
||||||
project_name_param, auth_url_param)
|
project_name_param, auth_url_param)
|
||||||
|
|
||||||
LOG.info('Full command: %s', full_command)
|
LOG.info('Full command: %s', full_command)
|
||||||
|
|
||||||
p = subprocess.Popen(full_command,
|
p = subprocess.Popen(full_command,
|
||||||
shell=True,
|
shell=True,
|
||||||
executable="/bin/bash",
|
executable="/bin/bash",
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE)
|
stderr=subprocess.PIPE)
|
||||||
stdout, stderr = p.communicate()
|
stdout, stderr = p.communicate()
|
||||||
return stdout
|
if stderr != '':
|
||||||
|
LOG.error("The command output error is : " + stderr)
|
||||||
|
if stdout != '':
|
||||||
|
LOG.debug("The command output is : \n" + stdout)
|
||||||
|
return stdout
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_property_value(environment_name, conf_name, default_value, conf):
|
def get_property_value(environment_name, conf_name, default_value, conf):
|
||||||
|
@ -114,16 +118,6 @@ def get_client():
|
||||||
return oslo_messaging.RPCClient(transport, target)
|
return oslo_messaging.RPCClient(transport, target)
|
||||||
|
|
||||||
|
|
||||||
def get_regex_from_array(pattern, lines_arr):
|
|
||||||
p = re.compile(pattern)
|
|
||||||
for line in lines_arr:
|
|
||||||
m = p.search(line)
|
|
||||||
if m:
|
|
||||||
LOG.debug("The field value is " + m.group(1))
|
|
||||||
return m.group(1)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def get_regex_result(pattern, text):
|
def get_regex_result(pattern, text):
|
||||||
p = re.compile(pattern)
|
p = re.compile(pattern)
|
||||||
m = p.search(text)
|
m = p.search(text)
|
||||||
|
@ -131,3 +125,7 @@ def get_regex_result(pattern, text):
|
||||||
LOG.debug("The regex value is " + m.group(1))
|
LOG.debug("The regex value is " + m.group(1))
|
||||||
return m.group(1)
|
return m.group(1)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def uni2str(text):
|
||||||
|
return text.encode('ascii', 'ignore')
|
||||||
|
|
Loading…
Reference in New Issue