diff --git a/checkman/ospf_neighbor b/checkman/ospf_neighbor index 7acad47c53308d2df19239eb277da99d3899093d..69a62abe9135e335d65e4c364003a8213f452087 100644 --- a/checkman/ospf_neighbor +++ b/checkman/ospf_neighbor @@ -46,9 +46,10 @@ description: {NbrOptions:} A BIT Mask corresponding to the neighbors options field. - Bit 0, if set, indicates that the area accepts and operates on external information; of zero, it is a stub area. - Bit 1, if set, indicates that the system will operate on Type of Service metrics other than TOS 0. - If zero, the neighbor will ignore all metrics except the TOS 0 metric. + Bit 0, if set, indicates that the area accepts and operates on external information; ff zero, it is a stub area. + Bit 1, if set, indicates that the system will operate on Type of Service metrics other than TOS 0. If zero, the neighbor will ignore all metrics except the TOS 0 metric. + Bit 2, if set, indicates that the system is capable of routing IP multicast datagrams, that is that it implements the multicast extensions to OSPF. + Bit 3, if set, indicates that the associated area is an NSSA.These areas are capable of carrying type-7 external advertisements, which are translated into type-5 external advertisements at NSSA borders. {NbrPriority:} The priority of this neighbor in the designated router election algorithm. The value 0 signifies that the neighbor is not eligible to becom the designated router on this particular network. diff --git a/checks/ospf_neighbor b/checks/ospf_neighbor index fed32f840964eac105545583795423d188313d5b..7ba6415458c0f90e6e74ae20f35cde3b497c6b9e 100644 --- a/checks/ospf_neighbor +++ b/checks/ospf_neighbor @@ -27,11 +27,17 @@ # Author: Thomas Wollner (tw@wollner-net.de) ############################################################################### # -# Th.L. 15-06-2018: changed item from neighbor id to neighbor ip -# added events as perfdata (incl. metrics file) -# moved part of the output to long output -# a little code cleanup to better match coding guide lines -# 03-11-2019: moved 'events' from infotext to longoutput +# changes by: thl-cmk[at]outlook[dot]com +# url : https://thl-cmk.hopto.org +# +# 2018-06-15: changed item from neighbor id to neighbor ip +# added events as perfdata (incl. metrics file) +# moved part of the output to long output +# a little code cleanup to better match coding guide lines +# 2019-11-03: moved 'events' from infotext to longoutput +# 2020-07-26: added parse section, alias, wato for alias and state +# +# # ############################################################################### @@ -49,34 +55,27 @@ # 1.3.6.1.2.1.14.10.1.9.172.20.2.214.0 = INTEGER: 1 # 1.3.6.1.2.1.14.10.1.10.172.20.2.214.0 = INTEGER: 1 # 1.3.6.1.2.1.14.10.1.11.172.20.2.214.0 = INTEGER: 2 - +# +# sample parsed +# { +# '172.17.108.52': {'helperage': '', 'prio': '1', 'permanence': 'dynamic', 'helperstatus': '', 'options': '2', +# 'state': '8', 'hellosup': 'false', 'helperexitreason': '', 'events': 6, 'rtrid': '10.250.128.130'}, +# '172.17.108.60': {'helperage': '', 'prio': '1', 'permanence': 'dynamic', 'helperstatus': '', 'options': '2', +# 'state': '8', 'hellosup': 'false', 'helperexitreason': '', 'events': 6, 'rtrid': '10.253.128.101'}, +# '172.17.108.58': {'helperage': '', 'prio': '1', 'permanence': 'dynamic', 'helperstatus': '', 'options': '2', +# 'state': '8', 'hellosup': 'false', 'helperexitreason': '', 'events': 12, 'rtrid': '172.17.0.2'}, +# '172.17.108.49': {'helperage': '', 'prio': '1', 'permanence': 'dynamic', 'helperstatus': '', 'options': '2', +# 'state': '8', 'hellosup': 'false', 'helperexitreason': '', 'events': 9, 'rtrid': '172.17.0.2'} +# } +# factory_settings['ospf_neighbor_default_levels'] = { - 'ok_states' : [8, 4], - 'warning_states' : [2, 3, 5, 6, 7], - 'critical_states': [1], } - -def inventory_ospf_neighbor(info): - inventory = [] - - for id, ip, rtrid, options, prio, state, events, permanence, \ - hellosup, helperstatus, helperage, helperexitreason in info: - inventory.append((ip, {})) - return inventory - - -def check_ospf_neighbor(item, params, info): - def ospf_nbr_state(st): - names = {'1': 'down', - '2': 'attempt', - '3': 'init', - '4': 'twoWay', - '5': 'exchangeStart', - '6': 'exchange', - '7': 'loading', - '8': 'full'} +def parse_ospf_neighbor(info): + def ospf_nbr_hellosuppressed(st): + names = {'1': 'true', + '2': 'false'} return names.get(st, st) def ospf_nbr_permanence(st): @@ -84,11 +83,6 @@ def check_ospf_neighbor(item, params, info): '2': 'permanent'} return names.get(st, st) - def ospf_nbr_hellosuppressed(st): - names = {'1': 'true', - '2': 'false'} - return names.get(st, st) - def ospf_nbr_helperstatus(st): names = {'1': 'notHelping', '2': 'helping'} @@ -102,63 +96,138 @@ def check_ospf_neighbor(item, params, info): '5': 'topologyChanged'} return names.get(st, st) - for id, ip, rtrid, options, prio, state, events, permanence, \ - hellosupp, helperstatus, helperage, helperexitreason in info: - - if ip == item: - nbrstatus = ospf_nbr_state(str(state)) - - output = 'Neighbor ID: %s' % rtrid - perfdata = [] - longoutput = '' - - nbrstate = int(state) - - if nbrstate in params['critical_states']: - yield 2, 'State: %s' % nbrstatus - elif nbrstate in params['warning_states']: - yield 1, 'State: %s' % nbrstatus - elif nbrstate in params['ok_states']: - output += ', State: %s' % nbrstatus - else: - yield 3, 'Invalid Output from Agent' - - if events: - events = int(events) - longoutput += '\nEvents: %d' % events - perfdata.append(['ospf_events', events]) - - if options: - longoutput += '\nNeighbor options: %s' % options - if prio: - longoutput += '\nNeighbor priority: %s' % prio - if permanence: - permanencestr = ospf_nbr_permanence(str(permanence)) - longoutput += '\nNeighbor permanence: %s' % permanencestr - if hellosupp: - hellosuppstr = ospf_nbr_hellosuppressed(str(hellosupp)) - longoutput += '\nNeighbor hello suppressed: %s' % hellosuppstr - if helperstatus: - helperstatusstr = ospf_nbr_helperstatus(str(helperstatus)) - longoutput += '\nNeighbor helper status: %s' % helperstatusstr - if helperage: - longoutput += '\nNeighbor helper age: %s' % helperage - if helperexitreason: - helperexitreasonstr = ospf_nbr_helperexitreason(helperexitreason) - longoutput += '\nNeighbor helper exit reason: %s' % helperexitreasonstr - - yield 0, output + longoutput, perfdata + def ospf_nbr_options(st): + ''' + A bit mask corresponding to the neighbor's options field. + Bit 0, if set, indicates that the system will operate on Type of Service metrics other than TOS 0. + If zero, the neighbor will ignore all metrics except the TOS 0 metric. + Bit 1, if set, indicates that the associated area accepts and operates on external information; + if zero, it is a stub area. + Bit 2, if set, indicates that the system is capable of routing IP multicast datagrams, that is that it + implements the multicast extensions to OSPF. + Bit 3, if set, indicates that the associated area is an NSSA. These areas are capable of carrying type-7 + external advertisements, which are translated into type-5 external advertisements at NSSA borders. + ''' + try: + st = ord(st) + except TypeError: + return 'unknown' + + options = [] + for key, value in [ + (1, 'non TOS 0 service metrics accepted'), + (2, 'not a stub area'), + (4, 'IP multicast routing capable'), + (8, 'is NSSA'), + ]: + if st & key == key: + options.append(value) + + options = ', '.join(options) + if options == '': + return 'unknown' + else: + return options + + parsed = {} + for ip, rtrid, options, prio, state, events, permanence, hellosup, helperstatus, helperage, helperexitreason in info: + parsed[ip]={} + parsed[ip]['rtrid'] = rtrid + parsed[ip]['options'] = ospf_nbr_options(options) + parsed[ip]['prio'] = prio + parsed[ip]['state'] = state + parsed[ip]['events'] = int(events) + parsed[ip]['permanence'] = ospf_nbr_permanence(str(permanence)) + parsed[ip]['hellosup'] = ospf_nbr_hellosuppressed(hellosup) + parsed[ip]['helperstatus'] = ospf_nbr_helperstatus(helperstatus) + parsed[ip]['helperage'] = helperage + parsed[ip]['helperexitreason'] = ospf_nbr_helperexitreason(helperexitreason) + + return parsed + + +def inventory_ospf_neighbor(parsed): + for neighbor in parsed.keys(): + yield neighbor, None + + +def check_ospf_neighbor(item, params, parsed): + def ospf_nbr_state(st): + names = {'1': 'down', + '2': 'attempt', + '3': 'init', + '4': 'twoWay', + '5': 'exchangeStart', + '6': 'exchange', + '7': 'loading', + '8': 'full'} + return names.get(st, 'unknown: %s' % st) + + # default checkmk states for ctsxSxpConnStatus + neighborstate = { + '1': 2, # down + '2': 1, # attempt + '3': 1, # init + '4': 0, # twoWay + '5': 1, # exchangeStart + '6': 1, # exchange + '7': 1, # loading + '8': 0, # full + } + + alias = None + notFoundState = 3 + + for neighbour, neighbourAlias, neighbourNotFoundState in params.get('peer_list', []): + if item == neighbour: + alias = neighbourAlias + notFoundState = neighbourNotFoundState + + if item in parsed.keys(): + neighbor = parsed[item] + + perfdata = [] + longoutput = '' + + infotext = 'Neighbor ID: %s' % neighbor['rtrid'] + if alias: + infotext += ', Alias: %s' % alias + + neighborstate.update(params.get('neighborstate', neighborstate)) # update neighborstatus with params + yield neighborstate.get(neighbor['state'], 3), 'Status %s' % ospf_nbr_state(neighbor['state']) + + perfdata.append(['ospf_events', neighbor['events']]) + + for text, value in [ + ('\nNeighbor options', neighbor['options']), + ('\nNeighbor priority', neighbor['prio']), + ('\nNeighbor permanence', neighbor['permanence']), + ('\nNeighbor hello suppressed', neighbor['hellosup']), + ('\nNeighbor helper status', neighbor['helperstatus']), + ('\nNeighbor helper age', neighbor['helperage']), + ('\nNeighbor helper exit reason', neighbor['helperexitreason']), + ]: + if value != '': + longoutput += '%s: %s' %(text, value) + + yield 0, infotext + longoutput, perfdata + else: + infotext = 'Item not found in SNMP data' + if alias: + infotext += ', Alias: %s' % alias + yield notFoundState, infotext check_info['ospf_neighbor'] = { 'check_function' : check_ospf_neighbor, 'inventory_function' : inventory_ospf_neighbor, + 'parse_function' : parse_ospf_neighbor, 'service_description' : 'OSPF neighbor %s', 'default_levels_variable': 'ospf_neighbor_default_levels', 'has_perfdata' : True, + 'group' : 'ospf_neighbor', 'snmp_scan_function' : lambda oid: oid('.1.3.6.1.2.1.14.10.1.1.*') != None, 'snmp_info' : ('.1.3.6.1.2.1.14.10.1', [ - OID_END, 1, # 'ospfNbrIpAddr' 3, # 'ospfNbrRtrId' 4, # 'ospfNbrOptions' @@ -173,3 +242,6 @@ check_info['ospf_neighbor'] = { ] ), } + + + diff --git a/ospf_neighbor.mkp b/ospf_neighbor.mkp index 4d52040a425801a39fc9d28a9275e4954f429a36..b3a155692273968a04519efaa6cbe033c063aa72 100644 Binary files a/ospf_neighbor.mkp and b/ospf_neighbor.mkp differ diff --git a/packages/ospf_neighbor b/packages/ospf_neighbor index beeb97fc32d0bc475d7abc1525e52af95878ca79..8b478bdf6d1fbc63c585715d3a5c60d5c8ca2aa9 100644 --- a/packages/ospf_neighbor +++ b/packages/ospf_neighbor @@ -1,12 +1,13 @@ {'author': u'Thomas Wollner', - 'description': u'OSPF Neighborship State Check\n\nTh.L. 15-06-2018: changed item from neighbor id to neighbor address\n added events as perfdata (incl. metrics file)\n moved part of the output to long output\n', + 'description': u'OSPF Neighborship State Check\nchanges by thl-cmk[at]outlook[dot]com]\n2018-06-15: changed item from neighbor id to neighbor address\n added events as perfdata (incl. metrics file)\n moved part of the output to long output\n2020-07-26: added parse section, alias, wato for alias and state\n', 'download_url': 'http://exchange.check-mk.org/', 'files': {'checkman': ['ospf_neighbor'], 'checks': ['ospf_neighbor'], - 'web': ['plugins/metrics/ospf_neighbor.py']}, + 'web': ['plugins/metrics/ospf_neighbor.py', + 'plugins/wato/ospf_neighbor.py']}, 'name': 'ospf_neighbor', - 'num_files': 3, + 'num_files': 4, 'title': u'OSPF Neighbor State Check', - 'version': '20191103.v1.2a', + 'version': '20200726.v1.3', 'version.min_required': '1.2.8b8', - 'version.packaged': '1.4.0p35'} \ No newline at end of file + 'version.packaged': '1.4.0p38'} \ No newline at end of file diff --git a/web/plugins/wato/ospf_neighbor.py b/web/plugins/wato/ospf_neighbor.py new file mode 100644 index 0000000000000000000000000000000000000000..898e6c3d605da2b531c9311dc4f9538300b24a24 --- /dev/null +++ b/web/plugins/wato/ospf_neighbor.py @@ -0,0 +1,107 @@ +#!/usr/bin/python +# -*- encoding: utf-8; py-indent-offset: 4 -*- +# +# License: GNU General Public License v2 +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2020-07-26 +# +# wato plugin for ospf_neighbor check +# +# + +register_check_parameters( + subgroup_networking, + 'ospf_neighbor', + _('OSPF neighbor'), + Dictionary( + elements=[ + ('neighborstate', + Dictionary( + title=_('State to report for OSPF neighbor state'), + elements=[ + ('1', + MonitoringState( + title=_('1 - down'), + default_value=2, + ), + ), + ('2', + MonitoringState( + title=_('2 - attempt'), + default_value=1, + ), + ), + ('3', + MonitoringState( + title=_('3 - init'), + default_value=1, + ), + ), + ('4', + MonitoringState( + title=_('4 - twoWay'), + default_value=0, + ), + ), + ('5', + MonitoringState( + title=_('5 - exchangeStart'), + default_value=1, + ), + ), + ('6', + MonitoringState( + title=_('6 - exchange'), + default_value=1, + ), + ), + ('7', + MonitoringState( + title=_('7 - loading'), + default_value=1, + ), + ), + ('8', + MonitoringState( + title=_('8 - full'), + default_value=0, + ), + ), + ] + ) + ), + ('peer_list', + ListOf( + Tuple( + title=('OSPF Neighbors'), + elements=[ + TextUnicode( + title=_('OSPF Neighbor IP address'), + help=_('The configured value must match a OSPF Neighbor item reported by the monitored ' + 'device. For example: "10.10.10.10"'), + allow_empty=False, + ), + TextUnicode( + title=_('OSPF Neighbor Alias'), + help=_('You can configure an individual alias here for the OSPF Neighbor matching ' + 'the text configured in the "OSPF Neighbor IP address" field. The alias will ' + 'be shown in the infotext'), + allow_empty=False, + ), + MonitoringState( + default_value=2, + title=_('State if not found'), + help=_('You can configure an individual state if the OSPF Neighbor matching the text ' + 'configured in the "OSPF Neighbor IP address" field is not found') + )]), + add_label=_('Add OSPF Neighbor'), + movable=False, + title=_('OSPF Neighbor specific configuration'), + )), + ], + ), + TextAscii(title=_('OSPF Neighbor IP address')), + match_type='dict', +) \ No newline at end of file