From 3bb79488029fd2a47da9c83678b4113b4786ef3e Mon Sep 17 00:00:00 2001 From: Thl CMK <thl-cmk@outlook.com> Date: Sun, 26 Jul 2020 22:06:01 +0200 Subject: [PATCH] update project --- checkman/ospf_neighbor | 7 +- checks/ospf_neighbor | 234 +++++++++++++++++++----------- ospf_neighbor.mkp | Bin 5724 -> 7266 bytes packages/ospf_neighbor | 11 +- web/plugins/wato/ospf_neighbor.py | 107 ++++++++++++++ 5 files changed, 270 insertions(+), 89 deletions(-) create mode 100644 web/plugins/wato/ospf_neighbor.py diff --git a/checkman/ospf_neighbor b/checkman/ospf_neighbor index 7acad47..69a62ab 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 fed32f8..7ba6415 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 GIT binary patch literal 7266 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 b68~QU{@a27J1^85NYtdz0tCts3d(;0uoP4L literal 5724 zcmb7{<vSgK!$9YXs}0kpo2$E-?qPD8%QbzuuA1(e?(XjH?%w3&jA_O+_x<p`@ALco z`*NQ1C!9kajgB75^W6l1aE7{o&75o?wsw}zZXjN69uXcMZaz*J4=1k$r{fowH)j$r z&<)|*mw(Utmy4UO-L~wnO4;9^yssD4J5RElvXmQ_)>gp0&2k&vlgXONiI1W$+thCo zAM1Y?pWRwrNbDZ8MxqDNyaCXlvT3Uq0nJD|-weI@J(8HeY@7D^+~*4klTx_@H!bdV zWZHoDKs<xH0sR17W^wRolUk#22jVS!Wgo&DzjqK(GBf4Xyp!1zGpH5WzUEX9rfH_0 zvZ14wXW`<U&22oCojpimS%!94lVE6~JV7|0h3bBM@esMo^{V!qKf)Dzak{V@eiqT^ z!{^S3K+PIm2x8sHn+Rb1_{xqKWMKDV)PNJfL__NoqQZ|%l}49~Ccf*S&n9)VD$CGt zBak(z)m(|rQAj~kzwbI&$f|k}BoAp+BebT8`9A&nXp{j_Y-5XoyX1`0PIrlDCjPc_ z*6bEYy7J9-vb`FO-dm&k*B>a5-}^;-BdDm`RDixG+q4Tqu<i{XFu3Aktc!?H)+p>q zjjhL)xl8|eAEZB1bvGWhhZU%n2GLgSY=_0*UdqrVX*sa9mg^qF=`9`A@-bBWzMpsi zx76oOt}UzDz8#AaBUEfS0CK1(7j|yCgNAMhoV<=(zq&3;O8#xB^4*O96vV}gj^Z)J zBVy}yAQJ(+CSQI<RNW)q{{@Qew8Q#m`upl&=TJT|eaF^c-IV`WEcRzQE3YJ)^+d4y zHyd!RfLimByG3r!cHCE(S(Ce%8{;_^OM1>>2J(k-<DR0Pdm|k)@7=RRo@Ud?mSed# zCN{2I*Nhkcc*$+<+#sx_H!FIc@<^sd|MdgEvLm*)$MRO5{V&Y5o)C3NjCYT}|80x? zl;THF-Bg!*1BcEfj}beU=KiY`0q8!#ul08+|N0Cdmt`AQ=U)(bq2d0Usvg}!3HHt% zLH(8Fc!r1JxP+7OfC_NEfKq8r5%rqej|8>=yM@S79Z(|vhT`z(hv)4>RCA;qH%?l% zkp+$eEHo(%E86t9(g{%fNJLFx^22AIamwN_Edga(yU7q&qEnfD<2QFpDFrB+I_46k zG$|4A0+Zp#hX?0VTcinOyfs5njFP!rWiu8K3&S3vL^z93LvsC`&i=2#zXQ1n(wSD= z&U~~55@5l{ra+33M2998L2H;-(DN8aA%8xqTAcy<N2!xjfmS8jJdR<1`TfHMf>Hrs zCij9dS(pQzLFEWP&PEt|epA}7DKpb&*hE|&V%C%@FOOQP@A*Yh8kqBe{QyZ$jWe|X zWu3bty~-LD%FX{(LIQC_^2hzz`q{zvL2Noy;=P%qR8PCPrdf8A6%6M4Rpj-k&35eY z^tA1|iG-w#%8CSFNEkN!ela(3QaU$KsU6!x5V0*YLvDbLEO;mc_<n{J840xg+WdL5 zPU%CKjzUlq>doiE{$2Q_ZgO)5ng(JD9Msm<wxw2*j0g>j*?Q`_TRVHk;>f-j9f(ND z7CoVU&!a^7lyh!Twqnz>RW3$}6Zaa<*v13}Z_A7ks;Megv$>X1?s{L1J_iI->flPU z>D-^Ad{ZnbKm)VfwmJ1}*mR|_asc43@%#+UsYjliP71@nJ<X(P;(q)E2c9vtAsjO< zSQ6lYc7Cq|7WYz#JyRt-TT+P~`r7yX-+R2>i6>EDhV{>Ydrg*hm9$k?Is$idtlWDj zI0%?kLhwztB4jqg1DIoqXLDs|O$N#A;E(0Ml%vCU<^xl5nVJ7<SZbqu&M_b3GY{y= zPf)m|)R#G2xgs1s@<Mk0vpd^-`0uvIlmzk5JKV2sJ2c!6zHAe}2KRChG^W>c*pSUP zli7LreKc2gNWZ+fXzOy9AOFS^9^%(}v)yMk?dXSl{%2`p(H5?lR|N9I6?%F`Ng%?u zpQmovO*K`_>iK$bq-LJysO@`$!8eHT^)1`V`Rl}A`ctzI?twF*3y7Aldk-)JT23x; zci>uhg>-tMzHBcvxbS&HYZmy15@|^r^c5Xjoi$^#-gXhaop#CZ*d7gz4i=<nT`L&6 zw#rb-3&+L3^q#+^f(JKP(C#(L;i~$c?ExHPBjmyW-94T5^G&QGje_tx!RP_Pfq15w z1xNHQ-XN{$p_Urpmm-9b3n~V)xR2v(&mkQ)eGUNi9%H>hv2xSdm+5ExUX7aNfIzXa zcESm%4f7!xl*)`V6cgr|P~v%E43dqMPaI_%Yitr6aB>{osoeO(^#Dj`nWh#a{jTg# z++LNWHw&P$gnTz{3P0S0Uw-F!f3|`AD%t9GnHO!N9my??Qeo|JBH1d-@pVE!<qWub z9@j=wI`+dlOuktq=EHD*5g&J*N(jANz%ZXf@0?LhzB2Ka8UqbobD*A;PDlsqPtX{V z__tTsM^Vv<vWDGh=g8VmD4u^4hbvZR$CJa2e0d2oes51871#B>ITuWMOAU>_1PV{2 ztxNnY7u%=(K?dHUSv~`wE0QKz1Vh7Xrb5waK0CMFG8idX@EgBaH`d_g-XGqW<{k99 zAy7Ht6I4>AYOcDOEOsOFC>_rCdGNHa_ATTkl7b^X)0u|eQj%m17qrs8&ZS1ObB!v0 zPe)S4SwC3LC=l5KGK*C>m}8^F6H}-LKR4ylVEnQ-bCfHuT0pBvc~>tKa=%<W6P2aK zRG<yScOtU`Sv$Qiy916*(0h)&)hqW$u4r8Y#uknUD$uSAjU9)D*Ozg7)lAf~E}1Nm zUD{WBC8clLklJLL3APw=qwl}8hzfjPy+h)4?sU9yLpvyJQujYK?FZFYEu+=JB;w8w z>G|AOMxvHpJ2gmG?#8s_eYxjT=%f3b=cj)Tm8$?+aflsV8Pf*MyR#7M_I}tt5A$&Y zdjTieVAC&23)PU=xfx-y3-Fv|l>YIEn|9o<y>TLJ+uoMM!)lMDGfQj6+$JFPl%TtH zYIyeH-uMrP4{u5Ro~2i-_%X%HOY;;{9SbLT*hX~F?@sU}Wn@<~48N)nvbZj+l2ga% zoV4;$8<IBWbPy=*sz1ghxEGZ&ZA+0ALn?hMzf3BSeX>EonvyTVCSMdbZk1c}h_7OA zMm!q6P2TV^3avrr?l>9kQ-!{+2#Kfq5;&#aRA0Pxyc1bj(V&|N!d5&baQiftYQ$03 zGWTQDUA8wJC0m{VkHDsW<EBzm`m0^*su^|D;kOGSNa3F>n-kIod%B%{vrnaH@^Bu> z4oSbSi@hZHvV2x}u@SkNmQeo1?zWBmpJ(EcV*@Wew^Kc)=>cy3eZg*hd=xV07s4E# z#iu)48sWb+m^ikj^zfDq6DBz9eWh1SD^9rn^m6gmy&}ClmAoDTwr3Y^73Q;-@GSi6 zbI^*VsHM&Q#R7FM^$+*!&dZ=4TnbpzkA6k9vgHL~<o5rI-Ku4OS#Ja*yR=lnE7ZT; zY{maosscfIi|3P%kg4+#K0Tv8*LgV{urNV92n0B(>8AO;kh5mUHRv{><z*oIiSI%# zC!;FEK*<yhd2_j&*yM%<g~RmYgGVdn7E$CA*Y%-faymrXN7C3AvUb&MokX$?!YYLL zU*da)$t8RFKSiA|zLN_@U+sFw7bu`T-J@uE8#>KTJt97jy*)GJl+DfoYOV`rn@?ad zuVNWk5iNbc?P(=p?MC6@^f1YHofRR{mtgQa(x#G-BVAiZMAd5NNx{wMyAoFzih9ie z`RUCW?|#&=as&U=I7_34^89O@oV&&#X<p1_%>fU^jTm9%GlOMViDN_mHSs)Ys`B1V z(hu$Z7Fkd#+e4jh2s=|lzP^UO@QRu{;bKQhJ3Ft0Mv{_zG|P`u%M!wdOY;8MCQ|*- zkmt{U+xuw~2_9513y-IN#N!%ab#-uquyG7=^fw0S!Pzf@o8~y;6q3=+sYzP8hMc6w z=cwpZX1?#(MExpW#;=P;a<zQ=OimdG^DY>j(T0#8KkhzRvfc>1y5V3FZz}c_(O$sf zJ2w@BA^LFdT#iBFqk<(7q+l;+M?><dES37QMj{Hrt5snOtbr84&`!3(w4SR$yY*gv zNP~!CmkiX?ruJsBmZ4uT<vNpu366vTq6Dcix89Hl#E(GbL&*gIL{qcM<YGBR|7xX8 z5c`ra4!$jgUx%~AK}vQ%)F?d}nXt>mFXE$`My*c&$z7VqFq#O}zrDhd+^DgGPv83I zTMeB~SdW~_cw*^i@GAgBR3{Uz2OB4Cqb(WeiA#s)qj=0hTCFLlDjM^fL0%(`NRE#Z zBmZy!^07$|FwwD6y|E*yYq|tL+_bSi8>BZ_IaU;@N5cQ_2@m11!f1j~09wD^yQZ5Q z0=rM7?*m}SvFxjd-kaFNu@U+X7`PePf%xugZ`Z*pZP25+vkd_qgIKB>2X9nVwETjY zVxj?3N>8s>Z&qKCP)6&R?tcDtj{-NJB`51fr=3xJ^R%C20s<6y0Z`cM3f@w_7SJpo z(-k0)Wmx<Evp()D)`wu~mfr`oDBOk71Z52%kU3JcK)^2o)|+PTLWF{RTLC&4%P6ds zqmSFm>OCVkR{AL?&G%C(ONhFN&Ywl>lE_mO0=t5%Ag6&e&^W<(wDm0VTvbyRmf%-e zhe@kHNxT_BRs@vOh57uT)5nNQ`wu#G7#$AJ;>zv1b|OxnQi?AqHI(hS1DFg4*BieE zxo2;fGId(^ft@&aJmg8?_12hFwI(h`=E*dQ)={;#S{1xX8vBx5@jQmfmRvO8F?>9` z43OL#d<rNsQH92?h%n=XA2o6gKw0sM!i01^rpPfUpmrcmciv&=o2TZiF+Yl+rg`d7 zBjyQ4{)-Yg^D+h2x;-{LWFIuTBTP3VbS=bR)`Xtw${Z=G`W!eqMYZ5Cef`9g6pIw6 z9!P70ZC{0s#0eS?lHwL@ays45Mhk^}3!k>>_|z%C%i9g5mnC1Y(%h^`u;h+SrU<{h zT;PrSrb6KWvFCVWr0G~SmaAw0f##C2+A>q>y<Hjn85PhiAp0UN0&&EG>ERd@WI&LL zhd#Wwc%0Db{y3aSN}S1%8W0{dTMZQUQ+3Yl2X<@q8j$E)94jP$dzN)~ZTeubv8SFb z$MS=sjUQ`~Cj+4OYMV=IT(+K(7lZXnTb!-7`bl*E6<CTbh9Z6XXa4gRD+4UzY_3Qt zTFsq+&mF0Pb=I^b8iVDF%1Sz<;E_F5eYmK3ArstMd618LBa}hys_=yu%{p|H5hJ~< zcB{ov+dtjrcy5EUs7U_HL_)CKgUn7~_h7qc!)!edb1)@qJu;yhP0Ni5le7hUd;;^K z4@=8mhW_VYK|;mTaoKtnOo6I<)1geZC@FMz{k<eX44slLt!l*F-0P^uvW0+Z**#Q4 z<wR}E*&G*>A38i`kt*k=Y~}$=$J^;x$2h9Au6=;dT^zaaJv+I2gds!~RGa{z+tJgK zXwTJUGUHp4;9GJaPYy$BU^F>vz<Q_G^nHz&k1gCoP>+$`g-L_8yXmT$$HkPk{1$WP zNki}>KPDzJJ!m4%Fi|`}7nHD`zHr_YZKd=o0~V%Qqa-gX;KAo~RWB!=b4qmiMI241 zK9)PC!4rjSHETQrA!+YzRKv9sD$7t$5{&&@lR+jP85CgB#zkn&r3(E6D_&aYfMS(1 zPiI9v?}k&&6Mt@<oSHe}?f3tDQfo6eS<7uhu)O~Dpix$qB|!Wl3f}^0!x6tdyM3Qz zM%YX6sM(Cx{L~qC;LhtZ^_leVlCXjw@#DL({&z=VQ*Wca{{A*yC-oGaQ}gI)nrYl< zp^|D+N<Si&qJHSdF7@trZk3Ei-{E$$HgC2q2}N3*eWcnX3$%@nhJ8%UH|at%Lov1~ zXg%p|mYDJN_hQdvzQLSR1WYDq;Sq>qx}(xVvWBxr8;(HYj9)_6GNk)FqIR7751oWG zo6Gj->eq*A_DYW%?Z})R+9t4BPD&kSu#GQEl8G|*fgNoa^TwW$^S`5EAz*OP$iR)t z19a77(qCsW<RJ^k8S~$+#t6$|W#Ps3CCq`zEmJc}FaAj{>2v1?fZ8}KFPf9kULp1* z#w*@3l3rha2vJSIu=6J@F$F8FeYm-s<&j%)u}i1+c-nf0PNR-=F6Klrk>LRS0~BN9 z*XeLkI=eFi_jq`ke=_RNH4qwOH(hoWCN#8H<f2K@s1*|%uO)6R>5B0w<wR)5u%Gph zjkTJSqgbs8sBvS2-yE81UO-RUMXbCL+1y@%<~0Z&R^%b$BDY{<DGZn&Hcqdji?psf zQ*?iaAa>o~<5X1Fi1=o!aJnf{SV}LI6uvs(QmrbkkFrQoI?B`KWxtQygY<g@^<<FL zYE1g5J`{Zr7ns9*&P0i1g&d-a;t(t*=57O}Uk62tGa5=cSg$>dJW8@n5yORtdapxy zWL9%N^e)*%^uba;ikl2x1Mw#_lub|L+@`b=Jka3VdXJFtU(@1ez79RzIk7l%!Xyy4 zmAx1h5q>n-A?E2IceKH<t2ONM9lGU7zRC|@de7w@Otq_D0Ix?IuJrvQh3-e5K5u!L ze!FdobIrkmqv2;73fxHcN0s002JG0B33Kk?L)dX&`Y%>@>H~hRIy^Ho#W*MV0ds*f z%g(4RTH5dsb}Qmw9RLXupDcbm=0Qay)H5C~PG2EgiPM1s@)SQnp?A+f5?T3+?wXiW z-Lkn07O=(LbkUuVHqDLj&0a;(?h@N-4z4H1fh;-Bk?}lju?63A((;qnE|X%-T-}n0 z7gDHB=boi${yFnOl5_J|T6N9dWEkN__Kve$-?I|_2?xn7M|@fGI~z<WL<bg|{jU2| zOa3tDKr&4Oi6s?FIJm?b&C&`>rmcxZbiGU~(UcN+Lf^qAx#G=5A?aGyO*6hs^q!o0 zhRB&F$dwKtGlfby!!FVv<#GfEu&46O!Sxenj-UQN?x#f8IepraT)TqxBgsq!!1u9j zym_S!?hEPl%LW2=5@FkcKB3eyJox0?W+{E42QT%|k;=L_lfbBx#n}H3)PgY0AY-0~ zMry=!@#Eb2t3_Ka;+foKyDhiR_r;dvM$;d$YtH@i0vGowA2D>E|N45UA2@gQGS?C% z<QZYBR`u}}J@0OMC?02THhrND5PvxZ?+G3~M3C<(`j*U{pX-FCu)xPZ=6;0rJ?{$b zU1`!}omK_;%N~(#RXV+xk@T@@-va`kx=2>K)P2}HZMYhWaMJ7EmQ4DYp?}3V(k$kG z8j^TUBDv^GQHW6?_U(`d!a41WuWFjF=KX>P$fv7HpM33XPwq&gR0jL<wI6_LwNrWF zUYbVtVJi91bM$zXG-$F^q`#Gi?+1amw#_U*nPGyleGc-4-S4W=uDSx&cz&Mes6h58 z7+0vJ7*`)l*&1uHNEDfm(|>KMBW(IKZ_eI@KFbfAgto?v>ZuyNy=VMHMbhiN{5=R$ yo&7aJYwaIVC&S0Vt9bH%ohH}snsuE+{xARkGXnpW?P{VUupk=d`fu{zy!ju@Xe8DE diff --git a/packages/ospf_neighbor b/packages/ospf_neighbor index beeb97f..8b478bd 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 0000000..898e6c3 --- /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 -- GitLab