Add parsing of snmp_traps for snmp_parsing service

Add paring of snmp traps and unittest, the tempest test
will be submitted with sending trap to rabbitmq.

Implements: blueprint snmp-support
Change-Id: Ibb4f4294dd95bfd1a37e9291318b2775bf1fedd3
Signed-off-by: xupeipei <xu.peipei1@zte.com.cn>
This commit is contained in:
xupeipei 2017-12-28 19:04:22 +08:00
parent 0eb920268a
commit b8cc22c719
3 changed files with 166 additions and 3 deletions

View File

@ -12,13 +12,16 @@
# 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 pyasn1.codec.ber import decoder
from pysnmp.carrier.asyncore.dgram import udp from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.carrier.asyncore.dgram import udp6 from pysnmp.carrier.asyncore.dgram import udp6
from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher 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_log import log
from oslo_service import service as os_service from oslo_service import service as os_service
import sys
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
@ -68,5 +71,36 @@ class SnmpParsingService(os_service.Service):
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
def callback_func(self, transport_dispatcher, transport_domain, def callback_func(self, transport_dispatcher, transport_domain,
transport_address, whole_msg): transport_address, whole_msg):
# TODO(peipei): need to parse wholeMsg and send to message queue while whole_msg:
pass msg_ver = int(snmp_api.decodeMessageVersion(whole_msg))
if msg_ver in snmp_api.protoModules:
p_mod = snmp_api.protoModules[msg_ver]
else:
LOG.error('Unsupported SNMP version %s.' % msg_ver)
return
req_msg, whole_msg = decoder.decode(
whole_msg, asn1Spec=p_mod.Message(),
)
req_pdu = p_mod.apiMessage.getPDU(req_msg)
if req_pdu.isSameTypeWith(p_mod.TrapPDU()):
ver_binds = p_mod.apiTrapPDU.getVarBinds(req_pdu) \
if msg_ver == snmp_api.protoVersion1 \
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
def _convert_binds_to_dict(self, var_binds):
binds_dict = {}
for oid, val in var_binds:
u_oid = self._convert_obj_to_unicode(oid)
binds_dict[u_oid] = int(val) if type(val) == Integer \
else self._convert_obj_to_unicode(val)
return binds_dict
@staticmethod
def _convert_obj_to_unicode(val):
if sys.version_info[0] < 3:
return str(val).decode('iso-8859-1')
return str(val)

View File

@ -0,0 +1,129 @@
# Copyright 2017 - 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.
from oslo_config import cfg
from pysnmp.proto.rfc1902 import Integer
from pysnmp.proto.rfc1902 import ObjectIdentifier
from pysnmp.proto.rfc1902 import ObjectName
from pysnmp.proto.rfc1902 import OctetString
from pysnmp.proto.rfc1902 import TimeTicks
from vitrage.snmp_parsing.service import SnmpParsingService
from vitrage.tests import base
BINDS_REPORTED = [
(ObjectName('1.3.6.1.2.1.1.3.0'), TimeTicks(1491462248)),
(ObjectName('1.3.6.1.6.3.1.1.4.1.0'),
ObjectIdentifier('1.3.6.1.4.1.3902.4101.1.4.1.2')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.3'),
OctetString(hexValue='07e10406070408002b0800')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.1.2'), Integer(0)),
(ObjectName('1.3.6.1.4.1.3902.4101.1.1.4'), Integer(0)),
(ObjectName('1.3.6.1.4.1.3902.4101.1.1.3'), OctetString('')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.11'), OctetString('3305115653')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.2'), OctetString('host')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.4'), Integer(1)),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.5'), Integer(14)),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.6'), Integer(0)),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.7'), OctetString('')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.8'),
OctetString('vimid=,hid=controller_controller,'
'hostname=controller,'
'Reason: nova-compute is not available')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.12'),
OctetString('Tecs Director')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.9'), Integer(1581)),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.1'),
OctetString('3e7393db-2def-447c-8cba-77bf29ab29b4')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.14'),
OctetString('compute is not available')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.15'),
OctetString('vimid=,hostname=controller')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.16'), OctetString('')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.17'),
OctetString('10.62.89.92')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.18'), Integer(0)),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.19'), OctetString('')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.20'),
OctetString('Asia/Harbin')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.21'), Integer(0)),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.22'), Integer(0)),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.23'), OctetString('')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.24'), OctetString('')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.26'),
OctetString('controller_controller')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.10'), OctetString('')),
(ObjectName('1.3.6.1.4.1.3902.4101.1.3.1.25'), OctetString(''))
]
DICT_EXPECTED = {
u'1.3.6.1.4.1.3902.4101.1.3.1.8':
u'vimid=,hid=controller_controller,'
u'hostname=controller,'
u'Reason: nova-compute is not available',
u'1.3.6.1.4.1.3902.4101.1.3.1.9': 1581,
u'1.3.6.1.4.1.3902.4101.1.3.1.6': 0,
u'1.3.6.1.4.1.3902.4101.1.3.1.7': u'',
u'1.3.6.1.4.1.3902.4101.1.3.1.4': 1,
u'1.3.6.1.4.1.3902.4101.1.3.1.5': 14,
u'1.3.6.1.4.1.3902.4101.1.3.1.2': u'host',
u'1.3.6.1.4.1.3902.4101.1.3.1.3':
u'\x07\xe1\x04\x06\x07\x04\x08\x00+\x08\x00',
u'1.3.6.1.4.1.3902.4101.1.3.1.1': u'3e7393db-2def-447c-8cba-77bf29ab29b4',
u'1.3.6.1.4.1.3902.4101.1.3.1.18': 0,
u'1.3.6.1.4.1.3902.4101.1.3.1.19': u'',
u'1.3.6.1.4.1.3902.4101.1.3.1.10': u'',
u'1.3.6.1.4.1.3902.4101.1.3.1.11': u'3305115653',
u'1.3.6.1.4.1.3902.4101.1.3.1.12': u'Tecs Director',
u'1.3.6.1.4.1.3902.4101.1.3.1.14': u'compute is not available',
u'1.3.6.1.4.1.3902.4101.1.3.1.15': u'vimid=,hostname=controller',
u'1.3.6.1.4.1.3902.4101.1.3.1.16': u'',
u'1.3.6.1.4.1.3902.4101.1.3.1.17': u'10.62.89.92',
u'1.3.6.1.4.1.3902.4101.1.1.4': 0,
u'1.3.6.1.4.1.3902.4101.1.1.3': u'',
u'1.3.6.1.4.1.3902.4101.1.1.2': 0,
u'1.3.6.1.2.1.1.3.0': u'1491462248',
u'1.3.6.1.6.3.1.1.4.1.0': u'1.3.6.1.4.1.3902.4101.1.4.1.2',
u'1.3.6.1.4.1.3902.4101.1.3.1.25': u'',
u'1.3.6.1.4.1.3902.4101.1.3.1.24': u'',
u'1.3.6.1.4.1.3902.4101.1.3.1.26': u'controller_controller',
u'1.3.6.1.4.1.3902.4101.1.3.1.21': 0,
u'1.3.6.1.4.1.3902.4101.1.3.1.20': u'Asia/Harbin',
u'1.3.6.1.4.1.3902.4101.1.3.1.23': u'',
u'1.3.6.1.4.1.3902.4101.1.3.1.22': 0
}
class TestSnmpParsing(base.BaseTest):
OPTS = [
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',
help='The default path of oid_mapping yaml file'),
]
# noinspection PyPep8Naming
@classmethod
def setUpClass(cls):
super(TestSnmpParsing, cls).setUpClass()
cls.conf = cfg.ConfigOpts()
cls.conf.register_opts(cls.OPTS, group='snmp_parsing')
def test_convert_binds_to_dict(self):
parsing_service = SnmpParsingService(self.conf)
dict_converted = parsing_service._convert_binds_to_dict(BINDS_REPORTED)
self.assertEqual(dict_converted, DICT_EXPECTED)