Add codes of sending parsed snmp trap to datasource

since there is no snmp triggered datasource, codes
of alarm datasource processing snmp event and config file
are added in test case.

Change-Id: I9a4f0c8405f52bf9269b0056d26b31fdafdad0aa
Implements: blueprint snmp-support
Signed-off-by: xupeipei <xu.peipei1@zte.com.cn>
This commit is contained in:
xupeipei 2018-01-10 09:02:10 +08:00
parent 042858d98a
commit ede475c7d5
8 changed files with 124 additions and 11 deletions

View File

@ -306,6 +306,7 @@ function start_vitrage {
run_process vitrage-notifier "$VITRAGE_BIN_DIR/vitrage-notifier --config-file $VITRAGE_CONF"
run_process vitrage-ml "$VITRAGE_BIN_DIR/vitrage-ml --config-file $VITRAGE_CONF"
run_process vitrage-persistor "$VITRAGE_BIN_DIR/vitrage-persistor --config-file $VITRAGE_CONF"
run_process vitrage-snmp-parsing "$VITRAGE_BIN_DIR/vitrage-snmp-parsing --config-file $VITRAGE_CONF"
write_systemd_dependency vitrage-graph vitrage-collector
@ -335,7 +336,7 @@ function stop_vitrage {
disable_apache_site vitrage
restart_apache_server
fi
for serv in vitrage-api vitrage-collector vitrage-graph vitrage-notifier vitrage-persistor; do
for serv in vitrage-api vitrage-collector vitrage-graph vitrage-notifier vitrage-persistor vitrage-snmp-parsing; do
stop_process $serv
done
}

View File

@ -11,6 +11,8 @@ enable_service vitrage-collector
enable_service vitrage-ml
# Persistor
enable_service vitrage-persistor
# snmp_parsing
enable_service vitrage-snmp-parsing
# Default directories
VITRAGE_DIR=$DEST/vitrage

View File

@ -19,6 +19,6 @@ OPTS = [
default=8162,
help='The listening port of snmp_parsing service'),
cfg.StrOpt('oid_mapping',
default='/etc/vitrage/snmp_parsing_conf.yaml',
help='The default path of oid_mapping yaml file'),
default='',
help='The default path of oid_mapping yaml file.'),
]

View File

@ -0,0 +1,19 @@
# Copyright 2018 - ZTE
#
# 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.
class SnmpEventProperties(object):
SYSTEM_OID = 'system_oid'
SYSTEM = 'system'
DATASOURCE = 'datasource'

View File

@ -12,27 +12,37 @@
# 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_service import service as os_service
from oslo_utils import uuidutils
from pyasn1.codec.ber import decoder
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.carrier.asyncore.dgram import udp6
from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher
from pysnmp.proto import api as snmp_api
from pysnmp.proto.rfc1902 import Integer
from oslo_log import log
from oslo_service import service as os_service
import sys
from vitrage.common.constants import EventProperties
from vitrage.datasources.transformer_base import extract_field_value
from vitrage.messaging import get_transport
from vitrage.snmp_parsing.properties import SnmpEventProperties as SEProps
from vitrage.utils.file import load_yaml_file
LOG = log.getLogger(__name__)
class SnmpParsingService(os_service.Service):
RUN_FORVER = 1
RUN_FOREVER = 1
def __init__(self, conf):
super(SnmpParsingService, self).__init__()
self.conf = conf
self.listening_port = conf.snmp_parsing.snmp_listening_port
self._init_oslo_notifier()
def start(self):
LOG.info("Vitrage SNMP Parsing Service - Starting...")
@ -53,7 +63,7 @@ class SnmpParsingService(os_service.Service):
transport_dispatcher.registerTransport(udp6.domainName, udp6_transport)
LOG.info("Vitrage SNMP Parsing Service - Started!")
transport_dispatcher.jobStarted(self.RUN_FORVER)
transport_dispatcher.jobStarted(self.RUN_FOREVER)
try:
transport_dispatcher.runDispatcher()
except Exception:
@ -88,8 +98,8 @@ class SnmpParsingService(os_service.Service):
else p_mod.apiPDU.getVarBinds(req_pdu)
binds_dict = self._convert_binds_to_dict(ver_binds)
LOG.debug('Received binds info after convert: %s' % binds_dict)
# TODO(peipei): need to send to message queue
LOG.debug('Receive binds info after convert: %s' % binds_dict)
self._send_snmp_to_queue(binds_dict)
def _convert_binds_to_dict(self, var_binds):
binds_dict = {}
@ -104,3 +114,51 @@ class SnmpParsingService(os_service.Service):
if sys.version_info[0] < 3:
return str(val).decode('iso-8859-1')
return str(val)
def _init_oslo_notifier(self):
self.oslo_notifier = None
try:
self.publisher = 'vitrage-snmp-parsing'
self.oslo_notifier = oslo_messaging.Notifier(
get_transport(self.conf),
driver='messagingv2',
publisher_id=self.publisher,
topics=['vitrage_notifications'])
except Exception as e:
LOG.warning('Failed to initialize oslo notifier %s', str(e))
def _send_snmp_to_queue(self, snmp_trap):
if str == type(snmp_trap):
snmp_trap = json.loads(snmp_trap)
try:
event_type = self._get_event_type(snmp_trap)
if not event_type:
return
event = {EventProperties.TIME: datetime.utcnow(),
EventProperties.TYPE: event_type,
EventProperties.DETAILS: snmp_trap}
LOG.debug('snmp oslo_notifier event: %s' % event)
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.warning('Snmp failed to post event. Exception: %s', e)
def _get_event_type(self, snmp_trap):
yaml_file_content = load_yaml_file(self.conf.snmp_parsing.oid_mapping)
if not yaml_file_content:
LOG.warning('No snmp trap is configured!')
return None
for mapping_info in yaml_file_content:
system_oid = extract_field_value(mapping_info, SEProps.SYSTEM_OID)
conf_system = extract_field_value(mapping_info, SEProps.SYSTEM)
if conf_system == extract_field_value(snmp_trap, system_oid):
LOG.debug('snmp trap mapped the system: %s.' % conf_system)
return extract_field_value(mapping_info, SEProps.DATASOURCE)
LOG.error("Snmp trap does not contain system info!")
return None

View File

@ -0,0 +1,3 @@
- system_oid: 1.3.6.1.4.1.3902.4101.1.3.1.12
system: Tecs Director
datasource: vitrage.snmp.event

View File

@ -0,0 +1,15 @@
# Copyright 2018 - ZTE
#
# 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'

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
from oslo_config import cfg
from pysnmp.proto.rfc1902 import Integer
@ -112,7 +113,8 @@ class TestSnmpParsing(base.BaseTest):
cfg.IntOpt('snmp_listening_port', default=8162,
help='The listening port of snmp_parsing service'),
cfg.StrOpt('oid_mapping',
default='/etc/vitrage/snmp_parsing_conf.yaml',
default='vitrage/tests/resources/snmp_parsing/'
'snmp_parsing_conf.yaml',
help='The default path of oid_mapping yaml file'),
]
@ -127,3 +129,16 @@ class TestSnmpParsing(base.BaseTest):
parsing_service = SnmpParsingService(self.conf)
dict_converted = parsing_service._convert_binds_to_dict(BINDS_REPORTED)
self.assertEqual(dict_converted, DICT_EXPECTED)
def test_get_event_type(self):
parsing_service = SnmpParsingService(self.conf)
event_type = parsing_service._get_event_type(DICT_EXPECTED)
self.assertEqual(event_type, 'vitrage.snmp.event')
def test_converted_trap_mapping_diff_system(self):
converted_trap_diff_sys = copy.copy(DICT_EXPECTED)
converted_trap_diff_sys.update(
{u'1.3.6.1.4.1.3902.4101.1.3.1.12': u'Different System'})
parsing_service = SnmpParsingService(self.conf)
event_type = parsing_service._get_event_type(converted_trap_diff_sys)
self.assertIsNone(event_type)