Support post event API
Change-Id: I985774ee17fa9c6c7b12e8daff5ec1481ebdfa7b Implements: blueprint support-inspector-sb-api
This commit is contained in:
parent
c771ad1a1b
commit
329fe51977
@ -24,7 +24,7 @@ VITRAGE_USE_MOD_WSGI=${VITRAGE_USE_MOD_WSGI:-${ENABLE_HTTPD_MOD_WSGI_SERVICES}}
|
|||||||
# Toggle for deploying Vitrage with/without nagios
|
# Toggle for deploying Vitrage with/without nagios
|
||||||
VITRAGE_USE_NAGIOS=$(trueorfalse False VITRAGE_USE_NAGIOS)
|
VITRAGE_USE_NAGIOS=$(trueorfalse False VITRAGE_USE_NAGIOS)
|
||||||
|
|
||||||
VITRAGE_DEFAULT_DATASOURCES=${VITRAGE_DEFAULT_DATASOURCES:-nova.host,nova.instance,nova.zone,nagios,static_physical,aodh,cinder.volume,neutron.network,neutron.port,heat.stack}
|
VITRAGE_DEFAULT_DATASOURCES=${VITRAGE_DEFAULT_DATASOURCES:-nova.host,nova.instance,nova.zone,nagios,static_physical,aodh,cinder.volume,neutron.network,neutron.port,heat.stack,doctor}
|
||||||
|
|
||||||
|
|
||||||
# Tell Tempest this project is present
|
# Tell Tempest this project is present
|
||||||
|
@ -9,5 +9,6 @@
|
|||||||
"get rca:all_tenants": "role:admin",
|
"get rca:all_tenants": "role:admin",
|
||||||
"template validate": "",
|
"template validate": "",
|
||||||
"template list": "",
|
"template list": "",
|
||||||
"template show": ""
|
"template show": "",
|
||||||
|
"event post": ""
|
||||||
}
|
}
|
53
vitrage/api/controllers/v1/event.py
Normal file
53
vitrage/api/controllers/v1/event.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# Copyright 2017 - Nokia Corporation
|
||||||
|
#
|
||||||
|
# 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 pecan
|
||||||
|
|
||||||
|
from oslo_log import log
|
||||||
|
from pecan.core import abort
|
||||||
|
|
||||||
|
from vitrage.api.controllers.rest import RootRestController
|
||||||
|
from vitrage.api.policy import enforce
|
||||||
|
from vitrage.i18n import _LI
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class EventController(RootRestController):
|
||||||
|
|
||||||
|
@pecan.expose('json')
|
||||||
|
def post(self, **kwargs):
|
||||||
|
LOG.info(_LI('Post event called with args: %s') % kwargs)
|
||||||
|
|
||||||
|
enforce("event post", pecan.request.headers,
|
||||||
|
pecan.request.enforcer, {})
|
||||||
|
|
||||||
|
event_time = kwargs['time']
|
||||||
|
event_type = kwargs['type']
|
||||||
|
details = kwargs['details']
|
||||||
|
|
||||||
|
self.post_event(event_time, event_type, details)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def post_event(event_time, event_type, details):
|
||||||
|
try:
|
||||||
|
pecan.request.client.call(pecan.request.context,
|
||||||
|
'post',
|
||||||
|
event_time=event_time,
|
||||||
|
event_type=event_type,
|
||||||
|
details=details)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.exception('Failed to post an event', e)
|
||||||
|
abort(404, str(e))
|
@ -11,6 +11,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from vitrage.api.controllers.v1 import alarm
|
from vitrage.api.controllers.v1 import alarm
|
||||||
|
from vitrage.api.controllers.v1 import event
|
||||||
from vitrage.api.controllers.v1 import rca
|
from vitrage.api.controllers.v1 import rca
|
||||||
from vitrage.api.controllers.v1 import resource
|
from vitrage.api.controllers.v1 import resource
|
||||||
from vitrage.api.controllers.v1 import template
|
from vitrage.api.controllers.v1 import template
|
||||||
@ -23,3 +24,4 @@ class V1Controller(object):
|
|||||||
alarm = alarm.AlarmsController()
|
alarm = alarm.AlarmsController()
|
||||||
rca = rca.RCAController()
|
rca = rca.RCAController()
|
||||||
template = template.TemplateController()
|
template = template.TemplateController()
|
||||||
|
event = event.EventController()
|
||||||
|
62
vitrage/api_handler/apis/event.py
Normal file
62
vitrage/api_handler/apis/event.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# Copyright 2017 - Nokia Corporation
|
||||||
|
#
|
||||||
|
# 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 datetime import datetime
|
||||||
|
import json
|
||||||
|
from oslo_log import log
|
||||||
|
import oslo_messaging
|
||||||
|
from oslo_utils import uuidutils
|
||||||
|
import socket
|
||||||
|
|
||||||
|
from vitrage.api_handler.apis.base import EntityGraphApisBase
|
||||||
|
from vitrage.common.constants import EventProperties
|
||||||
|
from vitrage.messaging import get_transport
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class EventApis(EntityGraphApisBase):
|
||||||
|
|
||||||
|
def __init__(self, conf):
|
||||||
|
self.conf = conf
|
||||||
|
self._init_oslo_notifier()
|
||||||
|
|
||||||
|
def post(self, ctx, event_time, event_type, details):
|
||||||
|
try:
|
||||||
|
event = {EventProperties.TYPE: event_type,
|
||||||
|
EventProperties.TIME: event_time,
|
||||||
|
EventProperties.DETAILS: json.loads(details)}
|
||||||
|
|
||||||
|
self.oslo_notifier.info(
|
||||||
|
ctxt={'message_id': uuidutils.generate_uuid(),
|
||||||
|
'publisher_id': self.publisher,
|
||||||
|
'timestamp': datetime.utcnow()},
|
||||||
|
event_type=event_type,
|
||||||
|
payload=event)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.warn('Failed to post event %s. Exception: %s',
|
||||||
|
event_type, e)
|
||||||
|
|
||||||
|
def _init_oslo_notifier(self):
|
||||||
|
self.oslo_notifier = None
|
||||||
|
try:
|
||||||
|
self.publisher = 'api_%s' % socket.gethostname()
|
||||||
|
|
||||||
|
self.oslo_notifier = oslo_messaging.Notifier(
|
||||||
|
get_transport(self.conf),
|
||||||
|
driver='messagingv2',
|
||||||
|
publisher_id=self.publisher,
|
||||||
|
topic='vitrage_notifications')
|
||||||
|
except Exception as e:
|
||||||
|
LOG.info('Failed to initialize oslo notifier %s', str(e))
|
@ -18,6 +18,7 @@ import oslo_messaging
|
|||||||
from oslo_service import service as os_service
|
from oslo_service import service as os_service
|
||||||
|
|
||||||
from vitrage.api_handler.apis.alarm import AlarmApis
|
from vitrage.api_handler.apis.alarm import AlarmApis
|
||||||
|
from vitrage.api_handler.apis.event import EventApis
|
||||||
from vitrage.api_handler.apis.rca import RcaApis
|
from vitrage.api_handler.apis.rca import RcaApis
|
||||||
from vitrage.api_handler.apis.template import TemplateApis
|
from vitrage.api_handler.apis.template import TemplateApis
|
||||||
from vitrage.api_handler.apis.topology import TopologyApis
|
from vitrage.api_handler.apis.topology import TopologyApis
|
||||||
@ -50,7 +51,8 @@ class VitrageApiHandlerService(os_service.Service):
|
|||||||
endpoints = [TopologyApis(self.entity_graph, self.conf),
|
endpoints = [TopologyApis(self.entity_graph, self.conf),
|
||||||
AlarmApis(self.entity_graph, self.conf),
|
AlarmApis(self.entity_graph, self.conf),
|
||||||
RcaApis(self.entity_graph, self.conf),
|
RcaApis(self.entity_graph, self.conf),
|
||||||
TemplateApis(self.scenario_repo.templates)]
|
TemplateApis(self.scenario_repo.templates),
|
||||||
|
EventApis(self.conf)]
|
||||||
|
|
||||||
server = vitrage_rpc.get_server(target, endpoints, transport)
|
server = vitrage_rpc.get_server(target, endpoints, transport)
|
||||||
|
|
||||||
|
@ -129,3 +129,10 @@ class TopologyFields(object):
|
|||||||
RELATIONSHIP_TYPE = 'relationship_type'
|
RELATIONSHIP_TYPE = 'relationship_type'
|
||||||
SOURCE = 'source'
|
SOURCE = 'source'
|
||||||
TARGET = 'target'
|
TARGET = 'target'
|
||||||
|
|
||||||
|
|
||||||
|
class EventProperties(object):
|
||||||
|
TIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%f'
|
||||||
|
TYPE = 'type'
|
||||||
|
TIME = 'time'
|
||||||
|
DETAILS = 'details'
|
||||||
|
@ -17,6 +17,7 @@ from oslo_log import log
|
|||||||
|
|
||||||
from vitrage.common.constants import DatasourceAction
|
from vitrage.common.constants import DatasourceAction
|
||||||
from vitrage.common.constants import DatasourceProperties as DSProps
|
from vitrage.common.constants import DatasourceProperties as DSProps
|
||||||
|
from vitrage.common.constants import EventProperties as EventProps
|
||||||
from vitrage.datasources.alarm_driver_base import AlarmDriverBase
|
from vitrage.datasources.alarm_driver_base import AlarmDriverBase
|
||||||
from vitrage.datasources.doctor import DOCTOR_DATASOURCE
|
from vitrage.datasources.doctor import DOCTOR_DATASOURCE
|
||||||
from vitrage.datasources.doctor.properties import DoctorDetails
|
from vitrage.datasources.doctor.properties import DoctorDetails
|
||||||
@ -40,7 +41,7 @@ class DoctorDriver(AlarmDriverBase):
|
|||||||
return DOCTOR_DATASOURCE
|
return DOCTOR_DATASOURCE
|
||||||
|
|
||||||
def _alarm_key(self, alarm):
|
def _alarm_key(self, alarm):
|
||||||
return self.AlarmKey(alarm_name=alarm[DoctorProps.TYPE],
|
return self.AlarmKey(alarm_name=alarm[EventProps.TYPE],
|
||||||
hostname=get_detail(alarm,
|
hostname=get_detail(alarm,
|
||||||
DoctorDetails.HOSTNAME))
|
DoctorDetails.HOSTNAME))
|
||||||
|
|
||||||
@ -49,12 +50,12 @@ class DoctorDriver(AlarmDriverBase):
|
|||||||
get_detail(alarm, DoctorDetails.STATUS) != DoctorStatus.UP
|
get_detail(alarm, DoctorDetails.STATUS) != DoctorStatus.UP
|
||||||
|
|
||||||
def _is_valid(self, alarm):
|
def _is_valid(self, alarm):
|
||||||
if not alarm or DoctorProps.TIME not in alarm or \
|
if not alarm or EventProps.TIME not in alarm or \
|
||||||
DoctorProps.TYPE not in alarm or \
|
EventProps.TYPE not in alarm or \
|
||||||
DoctorProps.DETAILS not in alarm:
|
EventProps.DETAILS not in alarm:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
details = alarm[DoctorProps.DETAILS]
|
details = alarm[EventProps.DETAILS]
|
||||||
return DoctorDetails.STATUS in details and \
|
return DoctorDetails.STATUS in details and \
|
||||||
DoctorDetails.SEVERITY in details and \
|
DoctorDetails.SEVERITY in details and \
|
||||||
DoctorDetails.HOSTNAME in details
|
DoctorDetails.HOSTNAME in details
|
||||||
@ -91,17 +92,21 @@ class DoctorDriver(AlarmDriverBase):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
LOG.debug('Going to enrich event: %s', str(event))
|
||||||
|
|
||||||
event[DSProps.EVENT_TYPE] = event_type
|
event[DSProps.EVENT_TYPE] = event_type
|
||||||
|
|
||||||
old_alarm = self._old_alarm(event)
|
old_alarm = self._old_alarm(event)
|
||||||
if old_alarm and not self._status_changed(old_alarm, event):
|
if old_alarm and not self._status_changed(old_alarm, event):
|
||||||
event[DoctorProps.UPDATE_TIME] = old_alarm[DoctorProps.UPDATE_TIME]
|
event[DoctorProps.UPDATE_TIME] = old_alarm[DoctorProps.UPDATE_TIME]
|
||||||
else:
|
else:
|
||||||
event[DoctorProps.UPDATE_TIME] = event[DoctorProps.TIME]
|
event[DoctorProps.UPDATE_TIME] = event[EventProps.TIME]
|
||||||
|
|
||||||
event = self._filter_and_cache_alarm(event, old_alarm,
|
event = self._filter_and_cache_alarm(event, old_alarm,
|
||||||
self._filter_get_erroneous,
|
self._filter_get_erroneous,
|
||||||
event[DoctorProps.TIME])
|
event[EventProps.TIME])
|
||||||
|
|
||||||
|
LOG.debug('Enriched event: %s', str(event))
|
||||||
|
|
||||||
if event:
|
if event:
|
||||||
return DoctorDriver.make_pickleable([event], DOCTOR_DATASOURCE,
|
return DoctorDriver.make_pickleable([event], DOCTOR_DATASOURCE,
|
||||||
|
@ -12,15 +12,13 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from vitrage.common.constants import EventProperties as EventProps
|
||||||
|
|
||||||
|
|
||||||
class DoctorProperties(object):
|
class DoctorProperties(object):
|
||||||
TIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%f'
|
|
||||||
HOST_DOWN = 'compute.host.down'
|
HOST_DOWN = 'compute.host.down'
|
||||||
HOST_TYPE = 'nova.host'
|
HOST_TYPE = 'nova.host'
|
||||||
TYPE = 'type'
|
|
||||||
TIME = 'time'
|
|
||||||
UPDATE_TIME = 'update_time'
|
UPDATE_TIME = 'update_time'
|
||||||
DETAILS = 'details'
|
|
||||||
|
|
||||||
|
|
||||||
class DoctorDetails(object):
|
class DoctorDetails(object):
|
||||||
@ -36,7 +34,7 @@ class DoctorStatus(object):
|
|||||||
|
|
||||||
|
|
||||||
def get_detail(alarm, detail):
|
def get_detail(alarm, detail):
|
||||||
return alarm[DoctorProperties.DETAILS][detail] if \
|
return alarm[EventProps.DETAILS][detail] if \
|
||||||
alarm and DoctorProperties.DETAILS in alarm and \
|
alarm and EventProps.DETAILS in alarm and \
|
||||||
detail in alarm[DoctorProperties.DETAILS] \
|
detail in alarm[EventProps.DETAILS] \
|
||||||
else None
|
else None
|
||||||
|
@ -17,6 +17,7 @@ from oslo_log import log as logging
|
|||||||
from vitrage.common.constants import DatasourceProperties as DSProps
|
from vitrage.common.constants import DatasourceProperties as DSProps
|
||||||
from vitrage.common.constants import EdgeLabel
|
from vitrage.common.constants import EdgeLabel
|
||||||
from vitrage.common.constants import EntityCategory
|
from vitrage.common.constants import EntityCategory
|
||||||
|
from vitrage.common.constants import EventProperties as EventProps
|
||||||
from vitrage.common.constants import VertexProperties as VProps
|
from vitrage.common.constants import VertexProperties as VProps
|
||||||
from vitrage.datasources.alarm_transformer_base import AlarmTransformerBase
|
from vitrage.datasources.alarm_transformer_base import AlarmTransformerBase
|
||||||
from vitrage.datasources.doctor import DOCTOR_DATASOURCE
|
from vitrage.datasources.doctor import DOCTOR_DATASOURCE
|
||||||
@ -44,9 +45,9 @@ class DoctorTransformer(AlarmTransformerBase):
|
|||||||
def _create_update_entity_vertex(self, entity_event):
|
def _create_update_entity_vertex(self, entity_event):
|
||||||
self._unify_time_format(entity_event)
|
self._unify_time_format(entity_event)
|
||||||
|
|
||||||
details = entity_event.get(DoctorProps.DETAILS, {})
|
details = entity_event.get(EventProps.DETAILS, {})
|
||||||
details[VProps.NAME] = entity_event[DoctorProps.TYPE]
|
details[VProps.NAME] = entity_event[EventProps.TYPE]
|
||||||
details[DoctorProps.TIME] = entity_event[DoctorProps.TIME]
|
details[EventProps.TIME] = entity_event[EventProps.TIME]
|
||||||
|
|
||||||
return graph_utils.create_vertex(
|
return graph_utils.create_vertex(
|
||||||
self._create_entity_key(entity_event),
|
self._create_entity_key(entity_event),
|
||||||
@ -69,7 +70,7 @@ class DoctorTransformer(AlarmTransformerBase):
|
|||||||
return tbase.build_key((
|
return tbase.build_key((
|
||||||
EntityCategory.ALARM,
|
EntityCategory.ALARM,
|
||||||
entity_event[DSProps.ENTITY_TYPE],
|
entity_event[DSProps.ENTITY_TYPE],
|
||||||
entity_event[DoctorProps.TYPE],
|
entity_event[EventProps.TYPE],
|
||||||
get_detail(entity_event, DoctorDetails.HOSTNAME)))
|
get_detail(entity_event, DoctorDetails.HOSTNAME)))
|
||||||
|
|
||||||
def get_type(self):
|
def get_type(self):
|
||||||
@ -89,7 +90,7 @@ class DoctorTransformer(AlarmTransformerBase):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def _unify_time_format(entity_event):
|
def _unify_time_format(entity_event):
|
||||||
DoctorTransformer._unify_prop_time_format(entity_event,
|
DoctorTransformer._unify_prop_time_format(entity_event,
|
||||||
DoctorProps.TIME)
|
EventProps.TIME)
|
||||||
DoctorTransformer._unify_prop_time_format(entity_event,
|
DoctorTransformer._unify_prop_time_format(entity_event,
|
||||||
DoctorProps.UPDATE_TIME)
|
DoctorProps.UPDATE_TIME)
|
||||||
|
|
||||||
@ -97,5 +98,5 @@ class DoctorTransformer(AlarmTransformerBase):
|
|||||||
def _unify_prop_time_format(entity_event, prop):
|
def _unify_prop_time_format(entity_event, prop):
|
||||||
entity_event[prop] = change_time_str_format(
|
entity_event[prop] = change_time_str_format(
|
||||||
entity_event[prop],
|
entity_event[prop],
|
||||||
DoctorProps.TIME_FORMAT,
|
EventProps.TIME_FORMAT,
|
||||||
tbase.TIMESTAMP_FORMAT)
|
tbase.TIMESTAMP_FORMAT)
|
||||||
|
@ -16,6 +16,7 @@ from datetime import datetime
|
|||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
from vitrage.common.constants import DatasourceProperties as DSProps
|
from vitrage.common.constants import DatasourceProperties as DSProps
|
||||||
|
from vitrage.common.constants import EventProperties as EventProps
|
||||||
from vitrage.datasources.doctor.driver import DoctorDriver
|
from vitrage.datasources.doctor.driver import DoctorDriver
|
||||||
from vitrage.datasources.doctor.properties import DoctorDetails
|
from vitrage.datasources.doctor.properties import DoctorDetails
|
||||||
from vitrage.datasources.doctor.properties import DoctorProperties \
|
from vitrage.datasources.doctor.properties import DoctorProperties \
|
||||||
@ -107,9 +108,9 @@ class DoctorDriverTest(base.BaseTest):
|
|||||||
if status:
|
if status:
|
||||||
details[DoctorDetails.STATUS] = status
|
details[DoctorDetails.STATUS] = status
|
||||||
|
|
||||||
update_vals = {DoctorProps.DETAILS: details}
|
update_vals = {EventProps.DETAILS: details}
|
||||||
if time:
|
if time:
|
||||||
update_vals[DoctorProps.TIME] = time
|
update_vals[EventProps.TIME] = time
|
||||||
|
|
||||||
generators = mock_driver.simple_doctor_alarm_generators(
|
generators = mock_driver.simple_doctor_alarm_generators(
|
||||||
update_vals=update_vals)
|
update_vals=update_vals)
|
||||||
@ -125,9 +126,9 @@ class DoctorDriverTest(base.BaseTest):
|
|||||||
expected_update_date):
|
expected_update_date):
|
||||||
self.assertIsNotNone(event, 'No event returned')
|
self.assertIsNotNone(event, 'No event returned')
|
||||||
self.assertEqual(expected_hostname,
|
self.assertEqual(expected_hostname,
|
||||||
event[DoctorProps.DETAILS][DoctorDetails.HOSTNAME])
|
event[EventProps.DETAILS][DoctorDetails.HOSTNAME])
|
||||||
self.assertEqual(expected_status,
|
self.assertEqual(expected_status,
|
||||||
event[DoctorProps.DETAILS][DoctorDetails.STATUS])
|
event[EventProps.DETAILS][DoctorDetails.STATUS])
|
||||||
self.assertEqual(expected_sample_date, event[DoctorProps.TIME])
|
self.assertEqual(expected_sample_date, event[EventProps.TIME])
|
||||||
self.assertEqual(expected_update_date, event[DoctorProps.UPDATE_TIME])
|
self.assertEqual(expected_update_date, event[DoctorProps.UPDATE_TIME])
|
||||||
self.assertEqual(expected_event_type, event[DSProps.EVENT_TYPE])
|
self.assertEqual(expected_event_type, event[DSProps.EVENT_TYPE])
|
||||||
|
@ -17,6 +17,7 @@ from oslo_config import cfg
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from vitrage.common.constants import DatasourceProperties as DSProps
|
from vitrage.common.constants import DatasourceProperties as DSProps
|
||||||
|
from vitrage.common.constants import EventProperties as EventProps
|
||||||
from vitrage.common.constants import UpdateMethod
|
from vitrage.common.constants import UpdateMethod
|
||||||
from vitrage.datasources.doctor import DOCTOR_DATASOURCE
|
from vitrage.datasources.doctor import DOCTOR_DATASOURCE
|
||||||
from vitrage.datasources.doctor.properties import DoctorDetails
|
from vitrage.datasources.doctor.properties import DoctorDetails
|
||||||
@ -94,7 +95,7 @@ class DoctorTransformerTest(BaseAlarmTransformerTest):
|
|||||||
|
|
||||||
def _validate_vertex_props(self, vertex, event):
|
def _validate_vertex_props(self, vertex, event):
|
||||||
self._validate_alarm_vertex_props(vertex,
|
self._validate_alarm_vertex_props(vertex,
|
||||||
event[DoctorProps.TYPE],
|
event[EventProps.TYPE],
|
||||||
DOCTOR_DATASOURCE,
|
DOCTOR_DATASOURCE,
|
||||||
event[DSProps.SAMPLE_DATE])
|
event[DSProps.SAMPLE_DATE])
|
||||||
|
|
||||||
@ -106,9 +107,9 @@ class DoctorTransformerTest(BaseAlarmTransformerTest):
|
|||||||
if status:
|
if status:
|
||||||
details[DoctorDetails.STATUS] = status
|
details[DoctorDetails.STATUS] = status
|
||||||
|
|
||||||
update_vals = {DoctorProps.DETAILS: details}
|
update_vals = {EventProps.DETAILS: details}
|
||||||
if time:
|
if time:
|
||||||
update_vals[DoctorProps.TIME] = time
|
update_vals[EventProps.TIME] = time
|
||||||
update_vals[DoctorProps.UPDATE_TIME] = time
|
update_vals[DoctorProps.UPDATE_TIME] = time
|
||||||
|
|
||||||
generators = mock_transformer.simple_doctor_alarm_generators(
|
generators = mock_transformer.simple_doctor_alarm_generators(
|
||||||
|
15
vitrage_tempest_tests/tests/api/event/__init__.py
Normal file
15
vitrage_tempest_tests/tests/api/event/__init__.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
__author__ = 'stack'
|
83
vitrage_tempest_tests/tests/api/event/test_events.py
Normal file
83
vitrage_tempest_tests/tests/api/event/test_events.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
# 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 datetime import datetime
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from vitrage.common.constants import DatasourceProperties as DSProps
|
||||||
|
from vitrage.common.constants import EntityCategory
|
||||||
|
from vitrage.common.constants import EventProperties as EventProps
|
||||||
|
from vitrage.common.constants import VertexProperties as VProps
|
||||||
|
from vitrage_tempest_tests.tests.api.base import BaseApiTest
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class TestEvents(BaseApiTest):
|
||||||
|
"""Test class for Vitrage event API"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super(TestEvents, cls).setUpClass()
|
||||||
|
|
||||||
|
def test_send_doctor_event(self):
|
||||||
|
"""Sending an event in Doctor format should result in an alarm"""
|
||||||
|
try:
|
||||||
|
# post an event to the message bus
|
||||||
|
event_time = datetime.now().isoformat()
|
||||||
|
event_type = 'compute.host.down'
|
||||||
|
details = {
|
||||||
|
'hostname': 'host123',
|
||||||
|
'source': 'sample_monitor',
|
||||||
|
'cause': 'another alarm',
|
||||||
|
'severity': 'critical',
|
||||||
|
'status': 'down',
|
||||||
|
'monitor_id': 'sample monitor',
|
||||||
|
'monitor_event_id': '456',
|
||||||
|
}
|
||||||
|
|
||||||
|
self.vitrage_client.event.post(event_time, event_type, details)
|
||||||
|
|
||||||
|
# list all alarms
|
||||||
|
api_alarms = self.vitrage_client.alarms.list(vitrage_id=None)
|
||||||
|
|
||||||
|
# expect to get a 'host down alarm', generated by Doctor datasource
|
||||||
|
self.assertIsNotNone(api_alarms, 'Expected host down alarm')
|
||||||
|
self.assertEqual(1, len(api_alarms), 'Expected host down alarm')
|
||||||
|
alarm = api_alarms[0]
|
||||||
|
|
||||||
|
self._wait_for_status(2,
|
||||||
|
self._check_alarm,
|
||||||
|
alarm=alarm,
|
||||||
|
event_time=event_time,
|
||||||
|
event_type=event_type,
|
||||||
|
details=details)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
LOG.exception(e)
|
||||||
|
raise
|
||||||
|
finally:
|
||||||
|
# do what?
|
||||||
|
LOG.warning('done')
|
||||||
|
|
||||||
|
def _check_alarm(self, alarm, event_time, event_type, details):
|
||||||
|
LOG.info('alarm = %s', str(alarm))
|
||||||
|
self.assertEqual(EntityCategory.ALARM, alarm[VProps.CATEGORY])
|
||||||
|
self.assertEqual(event_type, alarm[VProps.NAME])
|
||||||
|
self.assertEqual(event_time, alarm[EventProps.TIME])
|
||||||
|
self.assertEqual(event_type, alarm[DSProps.ENTITY_TYPE])
|
||||||
|
self.assertEqual(details['status'], alarm[VProps.STATE])
|
||||||
|
self.assertFalse(alarm[VProps.IS_DELETED])
|
||||||
|
self.assertFalse(alarm[VProps.IS_PLACEHOLDER])
|
Loading…
x
Reference in New Issue
Block a user