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
# under the License.
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
LOG = log.getLogger(__name__)
@ -68,5 +71,36 @@ class SnmpParsingService(os_service.Service):
# noinspection PyUnusedLocal
def callback_func(self, transport_dispatcher, transport_domain,
transport_address, whole_msg):
# TODO(peipei): need to parse wholeMsg and send to message queue
pass
while whole_msg:
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)