From 71e00a6684a70f3c7f25a830bb97a49e8343c807 Mon Sep 17 00:00:00 2001 From: "th.l" <thl-cmk@outlook.com> Date: Mon, 12 Jun 2023 17:30:44 +0200 Subject: [PATCH] update project --- agent_based/utils/bgp_peer.py | 85 ++++---- bgp_peer.mkp | Bin 15660 -> 15762 bytes gui/views/inv_bgp_peer.py | 8 +- gui/wato/check_parameters/bgp_peer.py | 255 ++++++++++++++++++++++ gui/wato/check_parameters/inv_bgp_peer.py | 107 +++++++++ packages/bgp_peer | 10 +- 6 files changed, 410 insertions(+), 55 deletions(-) create mode 100644 gui/wato/check_parameters/bgp_peer.py create mode 100644 gui/wato/check_parameters/inv_bgp_peer.py diff --git a/agent_based/utils/bgp_peer.py b/agent_based/utils/bgp_peer.py index 6792c53..616f18c 100644 --- a/agent_based/utils/bgp_peer.py +++ b/agent_based/utils/bgp_peer.py @@ -61,7 +61,7 @@ class InvBgpPeer(TypedDict): remote_addr: str remote_id: str version: str - local_addr:str + local_addr: str remote_as: str local_as: str local_id: str @@ -127,49 +127,48 @@ def bgp_error_as_string(error_code: List[int]): except ValueError: return 'Unknown' - names = {} - names[0] = {0: 'NO ERROR'} - names[1] = { - 0: 'Message', - 2: 'Connection Not Synchronized', - 3: 'Bad Message Length', - 4: 'Bad Message Type', - } - names[2] = { - 0: 'OPEN', - 1: 'Unsupported Version Number', - 2: 'Bad Peer AS', - 3: 'Bad BGP Identifier', - 4: 'Unsupported Optional Parameter', - 5: 'Authentication Failure', - 6: 'Unacceptable Hold', - } - names[3] = { - 0: 'UPDATE', - 1: 'Malformed Attribute List', - 2: 'Unrecognized Well-known Attribute', - 3: 'Missing Well-known Attribute', - 4: 'Attribute Flags Error', - 5: 'Attribute Length Error', - 6: 'Invalid ORIGIN Attribute', - 7: 'AS Routing Loop', - 8: 'Invalid NEXT_HOP Attribute', - 9: 'Optional Attribute Error', - 10: 'Invalid Network Field', - 11: 'Malformed AS_PATH', - } - names[4] = {0: 'Hold Timer Expired', } - - names[5] = {0: 'Finite State Machine Error', } + names = { + 0: {0: 'NO ERROR'}, + 1: { + 0: 'Message', + 2: 'Connection Not Synchronized', + 3: 'Bad Message Length', + 4: 'Bad Message Type', + }, + 2: { + 0: 'OPEN', + 1: 'Unsupported Version Number', + 2: 'Bad Peer AS', + 3: 'Bad BGP Identifier', + 4: 'Unsupported Optional Parameter', + 5: 'Authentication Failure', + 6: 'Unacceptable Hold', + }, + 3: { + 0: 'UPDATE', + 1: 'Malformed Attribute List', + 2: 'Unrecognized Well-known Attribute', + 3: 'Missing Well-known Attribute', + 4: 'Attribute Flags Error', + 5: 'Attribute Length Error', + 6: 'Invalid ORIGIN Attribute', + 7: 'AS Routing Loop', + 8: 'Invalid NEXT_HOP Attribute', + 9: 'Optional Attribute Error', + 10: 'Invalid Network Field', + 11: 'Malformed AS_PATH', + }, + 4: {0: 'Hold Timer Expired', }, + 5: {0: 'Finite State Machine Error', }, + 6: { + 0: 'Administratively Shutdown', + 1: 'Max Prefix Reached', + 2: 'Peer Unconfigured', + 3: 'Administratively Reset', + 4: 'Connection Rejected', + 5: 'Other Configuration Change', + }} - names[6] = { - 0: 'Administratively Shutdown', - 1: 'Max Prefix Reached', - 2: 'Peer Unconfigured', - 3: 'Administratively Reset', - 4: 'Connection Rejected', - 5: 'Other Configuration Change', - } return names[main_code].get(sub_code) diff --git a/bgp_peer.mkp b/bgp_peer.mkp index 322502aab47095cb19f46e0dcd836ddf4b8f97a3..516ed8629448dc176edecabe4598ca217129752a 100644 GIT binary patch literal 15762 zcma)@Q;=p&u&&#-ZQHhOThsd5wr$(CF+FWt)3$B9d(XeG&fPu{6|pL6U9FY*R%N{P zBw;iZP%L-28OYC-@0rs9*I%O_eSYvV8V<5)DK_b?sHLHky6P`ie1r{l{!WJQpfsvz zeY8qq>P|lNZxcgPL;HL)R#YJ9yrPTK>osKaKQ^e)M2S*n6aiubcN*V_JKSdpVP67Y zAt_&0IK};l61_W|Vcp+zSbZ;h4s7p%XM&#)R+thRK=R+WH<<#QwfZg3!N)1=jLYkQ z*w&)f4SgE{1D*NQ-e|p@ACHd5;_A>|D^6bcWxe%15{I_L18=SKb(kyi2ma@SYE?Ju z4Pf5*nlba)<>!6U&K?U)fWK+zCFYJRKkw@<J1$*vRw&`@WoKU`$%ZMdpwaC1=aiiM zD9j{sjiG0H_nkekJ=WKlHWOr-a6@B*q7C{hZX3~M`}Ot6oz@{}U+tB+pMzm9G%8mo z088JO@7J;ubZo7yJM5$ORTp?0T2xt%!`^JYecMB=z6haq>U@4vEdHjDzPmz8o%Z78 z`BxpY0;c{=4ey5X<lohI_q+?;$u|ZEM~4;V7Wi^W$)Lma^&N?xV@OU(p}0~)7kqmw z`#nvfnZ%lCYaQ-7d=d0MBhCbFN{+x@#%vV1jcrmhPiv6*lcz%W#Dg$NnospAq2v)4 zQ%`ETCLvDV@Ow@-G_GhD-_R>gd;AXuzN%2b!%WmC>40fZD+nx3V=#{`TKZ(0=Tkt+ z3sE*j84q3}YR9AcjLN$gY-@y-jdhv1OQ5dT`yA7fp6!9hL*Mu4474Q}v|2BR3X?A2 z4jF=He5dSUHFUWZFzZeLhtk*e#Q#xvH%R=o4Go_E3^?`f&Hv_v@Fgw&ksS29Dfsb6 z{rU+Z8%(D5CLte8M(_?|0qd2<4%$KMR@9DP`XKCL{Ci5+RX?}%Z?-hxs%~fd6-9>j z7il~_tzE{PPKF#ULWNy7b%c4WwJ@k+07IxN_d<k$^RZ#fPc(i+w-LMntsPtd&v#50 zln`br5K)rmA%PpH)yJ<W1N8Rg2vt0g*hr#$k5c85P>ufW5Jo`OHLohvNho|lvT$%g zJW-*dQ4kNEE!68-RAK&@h6;3Y+2iT<7Bc^5!qSoo%HR3TKI73_<{S6j(g^SH$379w z?u-7hm-#&Yb+%vVHgJtKTvXuOckmS6o9VmE>b&>pmGyb>X~r>KJ!C!khcPSf`^*v( zLUJX}-ORh)#v74m;DSA`={mpDW{(m7#(ctUzKVB*5q`|$iq3|yrTlVf<K;3HzG};9 z?d*CTe2MOUwKg(gw8WtdeH}kwJHI;&d?qEejt%&jdmSA}lt-H|czNjD6qHP7!z_e| zP?nX*!av|o=SMv6xA#gjsjXEzu3}+U$zN(%0{emrcC5cctFM9Zr(o5k=-T*ii2%~D zDkb_~6DqxUhFzut*jmPrHMxCl9CZiix&+qns7(B7u$4#e+wi*`TjEzK!ekYozm|q3 zkEckeG7MBEDHb%4+k4C!QPdu$1J}VMBBN6|Aj(qhsz^bBrkZoJpV;A)r6^9;@6&`T zaF^G$WN}xQb-6h^fnp0d>ci#ON>Ixm?O^r!oxXU@GWra-^D{1Na->#+Dz;gr9-J(_ zSS*Iqp6MNUoJC#{p0%nF+8WwcSpbd|+<{ZnjQ!?wOOA_3`jkzaaPZe?`$~8i$H*JN zsReg^2!q!X>s;4g%0Qy9-QcFMe{Se6i+gjs)c_m;h?qjCc=%)|vG~Z+Cw*XjphDKK zAY30@+mUYr4FVfM)U5+go@iPIP#sE8JQxz8V9=Mbgu<ASx_(`2`#if~@2IA%z#;qE zdm+SeC`p>OnBOp$xRxM`2@RF6WXJw=SE;Seq{DM6)|@WF;#p3CS3F{TyHq4xEm5io ztr~mgcAy<Xa-jfk?s&Wc&IWkGKJGhZ-i6`iVMTw*Lk<m~$1>>NR!l%2>NkjV!_%H- zeh(wMMD`reF5foS4_O&-4nI;7t<i7l587s+aU?%4KQJeANU2ZtTjZ?GTS#b@nRWkP zS!H)s-uhca*rcNvO3j<R7XoH4aaRo5#)P`7Q8yhgW9=(#-Qo-nm*QX~$6lDi@P+Y* zO?v5XMAG7e#=5p>6h!x&nABvr=uN``<||kftK=w)0iM#%1eZ=pekNHR-vdtZ1MIh} ziDky_ub3+xVZF`8fly*Ey4h>OK<cEeN)vrqCwZ*}#5N~OAE@U5-G1mJo-}<hjo%U^ z4%}03Am&VV;={Y$b=+#B3XiMlr2&@pm#1)EUqKDOoday7_5j(TOqB(QJPk|yPNe4* znE5r+7_WC&(>Bj>*4YE@N}6BS*~x^+609wG93lRNkXg(Df^eTZVBdIg?9Ov5avY|V z8>S54Wpt_PDuJ2xyH~@}nv64LHJU0Vng%5`seYb`e$t7;>a#Af-<m2ekF8>vDaE{a zk1oYFOpkgU7EHFr8ZSmBDaHUS^-_pmrT1iC<KK(?y<EJWA22u<tlcgB#&xH(0C!VU z=fQptE{;Hk*s$iccVGt^sBj2*(F`@J)Zv$t8Itn`ce79}yWrpg;jrVh5pd^<%1Mc% zmyTA~7G2ThrJ`;d>W#OV=MMY=jYI#OHDW2ZZ(hvjI$uC%A&~ePiJ$Ms@gqsYu;DXh zg%VJq6RZiBs}sdrds=6+uvUM`Az^+~GA`ox{#7{4D{j^?e&FwRv6c-(F);X0beei5 z`M47m>&o16dDf>v?t;B7y#ki%a3F2Ptd_jL@-V|wfEit|ardNiV-Yv)+}A}rHk>(P zyUyWbeOfZTlL`+b?E<51^R3>I8kfi%SLg=($l0Z(6dhu@3buyJ6Ug_l_26t;qEl7) zp%c=-&p^;~d#(;_>RXG_bSVgnY&*8;6`MR%tI2{yrl2BVW7JMby#hniM=iALl5tGS z(Q5U7cQ@T?ZK>4nV_s^IHSy!uYm8iUDnW@$7g$q)s0%`{SVI|NTi!4hEX)2@H#9n= zDKUd5D7lm&ae@~id6l8?>&BD4$>GQ7$up~2r>GdAAFx&944%svZJLJ$>&eA02FykY zj*@TO*;^Jt8)O_yro0*+u(y)w=|)spVtT-2WK=drrc7zD6g&D_EldC=?jMqlZ6y>O zeU5)?3CrT8$*{U%AFQf*AWMjI563vG5Q1;!)LW|T`Z%(tN8={CqsxZIbEHG#`NDt0 z>0X8CO#A@}kygdo3Gr}_DkVg5I+y^AWQ{j+b0E1RXDjpM5Fle!fg#Zg=|P}aF=n@D z4(WDf9nUydF7-~WR=sJv?4vaN`Fs2EOYdX}6kv`#Oo#(BXj?s=1-;?$U}(9FAu@fN zA14x{eP5ljueUeiQ<zfGj~_L#&yPlRe~%N<pb_?r53(mU`NV5@Fl91O+QV6oas>pI zx1eH`M<2A7Ae*T~Vvc&5u5~6P$fMW2H&8v;lsZg0I$s9iI1Ec=Xh2;<9+oq0p1JOv zgUmVd9dem^0xV#X<44aBI=()?{RP*uV{0_-DX7cNC^*W_uLsN{%iAP0J*!e|C|oj? z9>(P7@TSP$&yM5^%3mx;To*;=Omdjo(24QPVIsKkV#X|w`|)RiW}rIvvB6WsoA8bY zO9F(Re?az(INc7<yMW<JleRqZ<8CaGT~|EsPvr<2d}J{qz@fn8_qO<Nqk3WR{%SRN z3@d|Hb)Pt^J4N!cOXqbYz%OJ=!4xHmB_FuL{lqMTp-ZMlPteHRIlFdLM>tVX5^yEH z*mg3outx0++Mm87jj#~$iR3Y@*3f<xucTlHSbkgdy=!bD>bopab{Tpt>5=*{4X|dF zp}&1AW7!(J0c-Prd0UL<G*a3xDViL^FvjRa&&kbcYSo(Ds4KyMu5~KJ2IvR&ziJb% z+Q7-=6sCv0s-KRA9BTm^x$HakuoY9Z`3nLUata_uW^rmG4>EM^$G^$>4tfDl7<Tmk zPXBh3W42TFQNF<#HKP;lcBY+^K-<us@FX2dnula>1uI}t04jsXOH`JH1tlgvx1+&* zWU<CzcCfZu7<7ZeZ9=NhTesPI_o3_DwKI+4B_LI51dTl!EcN7pr;-It<7{o@W0_Cg ztvmj@21wDQuS)l04&}acb4EeI%7d}xvrh|lk?uK(6Ht6La+LQfkdD1cRv=i>+tu03 zB0{wbZD)1*%G+<ksV23KA0tV!!H|H>8ztn!#X?X0Hm+or4a8cRTKyJ*{ip8ia(0bp zW2}hnKz}C)Tp+OZsO-C3alKs8$Nq6y*bphwE3S`wagq#k8dQCg3_sM`tlN;pxQS~i z^JtA_7$tnh-MmUU-INT0v;p*JM+RP&l5_d$*<ej$8Kr+LZ9R1VflYSSyu-$&cKYeB zNxQ0^@TLG;v-9}F&7lD3HxcprK8)-dRPg51vR3t$5~emjg8VY`eHa$vCP3DM`xoa3 zeZ(K+meT8P;(^~l05=mdaaw!~Ed|S2$NtDsvgT-`aw=_OkE%}ZGjrj^zA8se6I!!r z&`2-~(LkZZw0iMG@ayw34QP-W%X@#-O`N+%?Ni$}XXA#4%CtPrpxoDyTt1iF(w94~ zv57d0i_A@X`7-)zmYFQ@kC^~kSp>E+)kZlVVO_nu?bv2Gi*#xlHp#9-_He;sTae8e zMbS*^iiZ>giU0$c06D9W^-!w@X=MO5mZ&0duE))rxjMvzlyLWk_^^?ASre>a(<Z0M zEDh+!q=q&)pA>K}948~nnNQ-S<u4idYMDw75=!sh1T@CiZ*`cwdiYSiV0JWzy_lQ1 z_N-wGU4Mv+vRa3FuT$OrZsMI?BpTx9*Vh{rXtHd5=J1o3-ll@Lg`>3-GftVc@ysT+ zAA#D{N1Cly6mZ%0UbErhY$NDa!lo@Kw>tcwsiT&0_s&X!rlCV=d*Di<B{ON8S8714 z9KM-~eZ@tTovNF1fP-dcjK`q)#MEM4fgYh^W}%N_c5x*inR%-<B%HDVOr^A(ud-WA z*Q$>kA*m)u^52V{lFTUxEIJgH<P0bY+5Xb(+(t31DO6llZD#6bdaREPxjny}3;X%t z$;lLglKb%nL=LM2;(${ym6jP_r7+e`N?8}xwX9~NtWtCdJ3@vypTQ48>iDCb{+|V= z_dkhuKbL2N!9OR2^FI$(zL0a}J4>K0B2ScYu>!V#l7*3E+7+DMFV0ji!>2LoYy+2h zqP}Pf0a5YE%vlq)Qfiy+!@Ab&cvJ?(^_%VP*;3p>b7$|F{^{=F9`5&_quwpzy|oJ< zf{UYBp|T);e2I(caj=FL<pGA$hBJ;seNI{RSBklE7(PeeK+GuAFA#bjBus84q}_ym z+8+uTPlih3h9lv?qqi&z7M>_#bjyWLNCZh#NB5M}hqDqrke{58FWwD@rFlHcR$uTd zo}2LCUM($x^EX#E@@hSA&!@jL0VFe0ymq_PwN5k`ooY(v!#oC9^)pSRZcxVJ6ZV+n zJr2FmDX3xlfIS`KA;_9lZW6bkF}gcc5wkn#=kX;31$2l$&>a(0yas@Rc4e;^>$NQi zIKSc`nfott;=gau>Of+|%4<bN6EZn8X7a`=ip*ezwEojVW7I%M=P{P#c-ZZEYl+qv z@R(}B8!6)2wwrfU6LUEZXPaEg)zf`KZRo6w-BJl{b%E%^+3`k-_a>X$t!ceMWyjmU z=Rv->PELE|Lfwf4+ZDSu=~<Xr*`m3VN?_TvsO)s0_0pK66{;NQ5@@2F*b4F8+wV?w zK1Cr&n#pp^%icuuo`mb{?&@;)VT#^^hKxi`hYuq|4Kkj<3zNTM)G$S6qn4>;i~>=% z-ufj^ZJU$zm=TAyzwjrtI{*xv)2ZFc6ZsniGLvN_TV~wURSTWNPV_ij<J2luWwfns z0V0bf?8tPrwQXI?AQk{XfUg@U1~<A*5)L}7RE19h?{_i*q+a>(HnlXO;QEWx<2WNZ zeWuy`<l+nMuQ~Kt%+jiym*@$?_2r#5pn@$ad<aS#s?BMSL2QI>Yc!2?aMkm$LJFSJ z#K3XkbP97m)HCjr!y(r1w<mr%!urrAa=UP;ys>e&PW?^(Jt%S=%W|t><f%Vy4wDQc z0tY+F6;RG(yP*qQsXP*72GYi>mTI2q)WQ9Z^k{=uPO-TJ<@}|z$O@#oBwOX=1mPWi zR4hHYu4$;eUP=%zAI;%04`3omQutFKP*}>&O#Qf}S2eN<@0OD_d?`B%uFosl$X*Kr zr(~4|JuO1T>@;iG`pag}fB)Rahd<{zmH571!BSP=eKpt_a}uOb55|)nHWj5Bhg<Rw z`u`15MHXc}dZ`gDQR6{j>t55M%P>C^gjKj>O)|IY{8Y_lMP9nD=fPCoTWn4=!{zdq zxqqT0Cod;A`Cx3NjBmfpO-*KYvChqkkQYQht@S;SL;zy=8M)f<34H7y1hA1iLvlRD zyPXqER!pvIESz#~P}2omNQa>(TqsKtM2@J^g-FIYc)0*#Em&l7(u|j|$Oor?qwg?? z=JQVZ4SUM503Iw@z?&(7<1Lf|8#6;|1&pasu2rcwBgy!4=^fj{bai{$;g;wROL8AM zoFKmZKWY#4=4y6)e%k9_rUN&B@UdREPM;u(2fuHOf82k*Zw9vLZU3mP@1-->+djsj zXddfwZEZB7VEUKamrvIBUh_e^qb1#BA_-L5{#s`!)13w<@R1}p@NHp1z7CzRbL|Iz z>gwD%XlpsZJ>K8u`J+wA*-}W9@rsXy5sud%VHD>uA01C!%JdVwO$TW+#RU~8HnKKz z5S!AsGbQ}sq#y*eCzjf0hLgt6%iWDX!TS<3nzf&v%&gZ3^5RR+N486x!NeohpaVw% zs#^En>028<pUTA7XC10p>zT?0bLPFo1COMNH_zJri{32r0I0$&FiZj=Wx)*H_CP+C z^z#Tx<FC*ylE3wQc?5obb32wsfC5=kFzgWCGDzVkZgKDUPHruk{P?&;xc+4u*V<ug zPuy?jsPHY>&(!pxC4R?D{Cu*Z{64Ajd}~QvN6$tg#SaZR$722`{kN2D9#tV$12n$! z`PX=`WHf>aTd}>f>j>xD@(IlfQCptpNkw1H+@n`3ki=NSl0cpMIyI(iVGZE$99H@1 zAi0Bu!z}VN>y#@NwEm-Cu^_HjAJ?h-;<_LhnrW_8wE@Cs=xU<JJ`6C`ldv0EM$S0R zSZLo#XwuhdW=-T56y*r&IoYPV7MVUMqfq1FhjRr<TSpjv&(S*Vn>UI*XpOGsvU-(F zGg3XJD~IR94H<T8ky=9QJaXeN)xsHB7X{=t-ohL3EhFZqTU~eQEcJt7CcPG0#@S@v z$!2uI*_7Bo=Fb~WjKG8TrwdcDa4zcl0(5I9Pima(zE4bFU6KB<!}dPj1d7yAQJU$8 zxpF%t(B!a*c#8NIfn@>giRE5Ffedy<xC!^rXeO#2KU9X^s*eUD<%CD3gaS$Rh}V&n z`H=g~4tL5<VF|@CcsC!xUi(5?(E#x=blcM8iO{kr1C#W_)+)L7*SN07=(;7ly?#t) z7fROp(_PR|Ve9*n8J$37GxUjmjQ4?2b@Cn6?Y?p7D>*BU_Do7$7e61@telUMOj=j~ zs?GBvq%->8llb3@)QU2Y<@$8p6?x{WA4}n>Kjcg-O*iG?6x#K;EvU)&npb+F<BnSD ztcv}1Q8vY*f=p`Qxy>Jfz;3UhD|5>Owb74L`8D=*b0S*o+r^z_JGWBYc8!fEa@uYW z-7oW^=75yh&RMRP?H*IcnVIcec0v_YCg1ItfB_56gM~=EPr4pP7zu}=nVarmo?HGH z*5tqu=#S!1hJ7_mZ(DE9c^=TkS)f836(ItZ1<Lr7&IL?+R`&f%@0-w0`YeFaT9mKQ zvs-&d9H;jpf$>929+v>)88FWo1+FGIztTpsPC)KNs%RMy45glmi7zYx&@;K^gMI?} zOM><BGN}HacWAg6ll{l2h==dTx4YqJko&GiJv}6#rcvaE(<g@gV^?6uZExU;a$Fq4 z=jf|H`ui;<M!@6S5m4IfeTg2>2#op{6lOyQ;%u@G<O(!kVp)OerX3AtUhZ!9=ZCgd z8>BT4Ik}D>S>4ZHwh$&YYR}KZJB-JI-MsX*c0rd^qXPY{P||QOscKWRMQgHrU1K2T z5*I#xUOsoK%&?Ecc#;&xzZvlwF!S5cuDXf`;K4R!wJbsX_%`ow0gY~5Si0zbT0=T6 z!oXY*X%GboTi$MYEAG(kz9#!gTbb}zhhX6M*z$cZ22N{r0rgI?d3$M=z>?G~=TqP4 zev|6qpO10-A^gen=TM*6f*vYRpL1i>XOmhs56Q07f7I!dbW7WBElj3WxQ2z6sHl%( z-M7g2-V(8<yB1eU+y*~pv)zi;8cx-9Gh92W<Vvf`Gi^ci9`_?r?Vgi6+q)e&(yIFm zal9aND<tuk!*^bPAn)ume-Lk}9%QIz+$kOWfz-Hm76ZW1?B*K%*8}T078mJV0_Wi0 zF%eC(jx+pLlKs8SpC|MD??Q^L<j__E9&zyDldMwL`XXsvcmk@fpZa<l2v9!gejhcc zM^x+nVP29v_K3nAS;&L_nX{h|1T|HGWVBi-5oXA(9Q+=bqMd<3Fu^72xNA!VSoCi& zaa>iSJQ_30;!?wWM+g|tD(7qLN6}&14_Z#JjqMh25U%R3=&YK_%|}A*#FJ7uwxPsd zvPo%b^`s&Dh2Fu@uUP{6{hc$q8be2;!#~sFE{WPNUwu5??|uFmJ<h;A023kZ1uUyD z=6N~anx}UUz9lpLjNP*vN8}jyvL|`lf>=)vE;u3!1c=A{ymvx1qltB`EfT#l8+C*I zk&aV3AEaLCo@FpY+9J^)sd~i;rw$qgme^{EOfb|$np725KMPPxqMq04qC^E#hT%M$ z`5c7$QvqfNKz`|4fzT_ui7^~E4$UAYr@uDQw8ICc^60c<&bxvXzH(hYmHH?6xsW2U zx)G&5^N6PAF#OFt4L&%}l}Py|T6sq=6_2LdMtSliH0#b1eWsd(ct(|P!r2wtrW^9L zhjiw??V!jUS;dNg6nTqgtjw>&I-b_$P<n)>)_S!!4MR8`(kOjW)M0r$cnr9wn7R+j zd6mU#n@ag(Z7+K&)f#=SJhcuS+A!GU*Bk5f%}4WRx@Ox4aP{_TY}e;l{ivm_$4svi zrL|Z^-*PGKBZdQy^5(D=E^h03BjHEx@7uY}i>>T`dqDSnW|*gvHb<wSpzH#1uc{#& zl6^O(g~js;t58Snn+^Hf)pMpnX6%LpYwPU9W=^G~8Cn4ETQXN+CJawXZ$rMvj*%V< zab=dZoK&c`t~^!@m_(v2HIb2FS1CQX8Y{XKi>^L~8oDjWv$f7(r|RCXv!AV^x_z^v z>nen1@fTT#Vk+-$va4rp`5w7~Tro~|UiB<mQ62>);;PUa^G2v2kn;qnSGz;x<^GeD zk#s6PC{<&HnV`d?&2{iPtv@h?PCP-x-A!PwB%B6=wKwynB%UI&fI}?kieC^v<Yp;# z7yB0Fi5~v^zc9a@{i7u71N{MnxkhN`@C3gfKE_x~df2#r9q9N>G#~mkd3~FK%|^5P zU_qsm6=|9IN39>xM$96fXWlSIJ{<eReZM^bcH$l0bvG7|0j!Viz?h-;i@0Z%+-Vl` zq#;@vah=GN>``XNu@lWFqvde8d$t9gP|R<44EOy02R9;aeuVp;ygL^|mZt(c#&V&x zn@Q=><kd&@#2Na&F2?&jE>*Zcvf!B80AmI>p>53Dra8~wYq)XYUv~Cv1o1Kkf+4P- zmR!r7{LXxTy^n+vV9_&^6S*gPQ9PF_qm|BeLR*7cbDDPvpt#U}O`BHUi+H-=ppPw; z>HAm2cYfVDD1|Lm2;#X)k}lAJW@L;s08Y*ARUnLG-sd8iuU}$VkeWHMGW44Tu~JEb z4tTGhM^KAf(!PZV;X3C^m8lu#rp#9H;k+fd$FQ)fcrzX;O5x$Xefxf`X3NO{u%BJ^ zZw7jk9l4<#a033l%jNJ26JY6-m|d(6Ai^9eSYe&;4(%w56B@iXF3_{76U2g>3?y;~ z6AJFvVuTFR%XsPD6RH=&b3(pDj*;P>vz!wh8Vwe%$AfbE0Aj<Ak@)X}V^&wfy||&7 zFs0@=!_2w&GhicLrj2{?9LMm1_P@3r)Z(~~LH57C9aR2JNcMvhwF9{hN%oZt!S@rQ zBjP0nVTL4&kx2vy<Y|z?^~8KwIR1MI`4q%|97UKi5D73T!TGW_cBbAxct<MiUf)&t zq{*FX$NE)nhI9#lz|jKTc93=B0hLLt;Kh8D0*RW=u?u^ogTzc5V18$&fEFyXO;8%t zLoOhY+f~XDAPR3kPe8K^MY7@{$auPO0bc<BZfk)!HLB<3m>6caEEl+Kwu+NX-ADFl z;H1jO7~ID4)%iHe6~~t>HmD1bGjhjrPboZ_Kq_;>R5$79!Gja-%or?Oqb2+-gocj| z`%-ZcMi1IPJu7x<oe%yll4irv*wENAuvZfR;x|&+C2d%kz_wyJ3%rJ4*NlQ)r}1hR zWSNlvEj$|{&3c+$tfI%Xa9M<}G~;Ma2q&X<U+lDH8z3eDFF<#rj3{5cU1DgAYs`>j z&cYP-<wW%FAJ5HU#s3#I5TOFnsedb1z({hRFhj)u!iefzp&5f2fr-VmMTaSr!V5%H zTpr(>YYDlLp*!M&N%_0pLghr(mvNYhAkdSIx}8}_=#l1r;)E6}xBz)V5+MZ`>a$R} z4q1W}<rN(V*oHnK865-|OhD=@iW;h$Pz@`S=puZ}I20SPX!CNQsc16_SX$ut*{(x* z9ye$VGEraL3W<^`eo|Nn2~l_$fdU=J32GmV-0E!tT+U;$sMs$Q2VXc}csIozhgCSM z@4UpvW~72fISFCH;t=dKXrLMma|$eXdx18E$84afu|7SX#XL)2FERB1Bnb}(2iH9G z$tYuPZiq@VGz0n`&t5jQiOehr8Kk=SUYt;%aRWcYyhB7>6kJH6``&nH$`2DWp_G5X zm3)=gtJkN58Pyz$4t_#2eFTgr)~iahu26_HAnaU|4v$h)?;AH+c_|CYxt}d7hSr8{ zBGh%*jD-#pKO>q|VTIO)eL@^}q5=shg?A{tpH_|b__?tokGlp5Bth2ABh*o<<Ms8d zkL`aG8qcQbUo<e02{VKLWqN@Ju%(TLG~<}~5G8*%h~rqPxLCc(4Y)I~Bk0QIe|n0* zHNsX~Z8MJ-vqq%&;Z%K*(M!51YnqpX;0dH-Y{wPm=-Y$<ZQi5`3H`G@++n3=11nFV z-$F16X={n|n=OQ!y9Ov|lNm%^j%#Z84lC$LuTd&QuLTD})L9P!tOHfg0S?l9ILef( zZ<N@$QOT~zh(U{a@J?#wUlOeV5ix1f{*#~H&Uvxl|7tltrs@~dKLL|EtJ%${{*&W* zto&Ctb31^ZpnZ0O%2ElsbBT>jzuT2*R7udv{)%FT;^{XL=9gqF2dsuO0*8f6xy)_t zg-_vBTANOoDzPS+XpS1~#sJ4*nW7J<h@QF*FtJ8lyO{Nu2T$Qu9S@wJEJBtEq_k%r z<nHHnSLa`+QKt0qHSuHcYW>}P=u}ia9L@B1bpDJ$50)BW=Y^Y!J=MlSNdYS@2}TdZ z=zEJt(RU?R)<TmZYILuCVy$e!0oAc!8QV+7$KnbKC-VS4p^E8m$iRd6*XG1n*c9$L zl@DqGX%U`49+p!YzWiulWe{!jTu2J~s6S$LP=|=UzknU!EG7s)hm@?!SdcW@IGnih zVL|*fuxhw0Re_UBZ$ikwfQhgn&L4vJZwK;!mnEy1q}uLo7O6hnz3F!4`J5z6l0MuW zKQiq43lTh=rYLlqiGq%W`7*g7cY#Cb+d~<?zVuW^r(iFm0XH{8eaklQ3A%YOdO@hV zU;@Kf1xnmN&#IjCR3BSZT<@`_dUL(Qp_^F#Jf0qtpc~H*Xp4|_+2{}tH(3^iqu__% zTS_gDFl4Z|!_sQa)DksZtL}P)k~kT8wHw3SDuQ{%Bn&qzR#th~?LzH)KXI+08)e81 z-#TfCBBzj@%KyI4I%?o%dF_`MfvGBUSD#sw?qgCEgPWW(%5;Qc^py&C`TrU}QIUD; zTUvP-+WjxqqLDxG)DH_o8zFq(KMgB{I9NZ1oRTB<*gu3yZ=Cr4p0;1!ZOUKY!2)Bw zKL9v{o1bqEY9|t(TeJfg6(V8e#krT9u~8v?c&|?MK?Kii+d-5YZoQhXSo9`CpOvS} zg1r$&k({2MEB3Tgu5e~N>Iww^Des5I!mxEKA#{bYht;rljK3eC*m7=Yh^T@pmiPqI z3x>ltmzFj2M!iNktbk5eeD86M<)Cd}=qo7Ds#~4P+gSY2DU*C)*cifdfru4~;R~bv z_ypgPiU~w`g6k;Xo@NjqtwJ;$Lu64&p7#Q<UXM8s%KEET*NcLmzXSKTzENaqq@AvG z!Ucz|V72`Td~F4Bz0qyFG3)WlDxUTlLhe5Z(4c5WH+9TPrV+{!IG4>OJ7`}u3}C{k z?ZE+Vk1W9A_10m`R^Uy14x8C8CzuhH5y2yFdC`R}4Yp6x)R#RT93qj}|L%}qrHR2Q z<CcNY1PMopLru^ESx>3K6+{LS4!R=-m8~x`$os`SUVocoy=_p8zz<qL2Um<60%>b? z&c#)Gn0oR~irc}EJcAH|4}i?I<9c<FHKmiQtA=*j*??C=xX9AHwEuENRX^xYr4wSb z1F|tv6@?C_<d+aInyu*@i3s9#$HpAwga`duE}V;Z2M!|{HsT}hP7yY}K$TQ_6?7qN zNqZJ_lhUR|=S@c(tvozJ8#Hr3J{VQ_VsdeSP$5IlkPDRWum7VT=3Mrxg||s<GGxbd z@lFHLuT<+`&ZC;~8)@?|PTvkpbxYW3dT2)E?O+6E(b4ct^7z=B2ttF=$sQOuh`4*( z^c%7-<Qr+FxKAuFtG2AYKe8z&3>Pjb52>yevhx+L5wvgtI=XZiSh#9YWpY4&K`<NA zowIe*AR1>*Zq7&{YIIp0i)cmKVJ*8he7s6?Jpl@^HT=mCqBXn*3LW`jzshf1ibF;l ztm9W`>>9*DSytp7DN~E*2?QIjpo7aJ)-ZQ1-b=k(4MSFN@IzHQ>4jIMKqzfdVygs` zz3VJL#Kee|moCPkhF2e$N_26XhGg`IPp(V(v5a1=OAsW^{jY3veqX3wB2^$h@b+$J zk<LNLY+$e{q`gQQDa_8Y9&fk1{h(aKoZPN|l$8Vq6eq*CNeyoZhu;Ar#%&U{(R_J# z3W<T0&6N>(x0s;m>_LQv>YlzVYFK<+1{q&TD_#;4b_+?-Rew=<k#t*b$VAl+SL8-4 zs<`2%0L3>=6iMrt-R@`hkZp`%kf`-=JnlijXyT|aXux&?dkCMMHOhOOBQ|}0dJ?*c zkv*|~6nbY%?a8>Qi*zZO5fffh+grq;&rEI`ay|c%`DIe(C5%-97W^vrW6uat=p3(4 zp+jXwu8aLoc`s>7`ZLUy>&^0vNi7yTF#o3<)IHtoAIDFn3Jc4zAF3j-ftvvy83Cya z89ytd40_lDMdCPZ)9@fKj&I#)Uq6(U_YnEQXi>K%W5vHq4|vUkUicgZpK<`aJ|j&; zd^b--4$Kj%cF=$>ACQ9&;vwMW@6W@ieX~7P(s23!QJ#|jd%XWpZC&QvoV`m|uKzfv zy!<Rm@*nK}yk(Pp8>x7p^%k^r|KuGQ?*2sfb9!U{%x*hyalQI~W1OAk$GI6hxLkQi zwz*HXz09w_c*U02e4H@w)N^f5r(6}OyT=&fC=#EzUS7RD^LvZu*)i~zrYD*abh1M~ zYQ08F0NOiOeY#qTX#FuedVcPl&LlNq{XvCpW(`<J%H$xbQ2YKP_XGqUz?f#|AApQb zhsj|+WS&M92!mqRmbbRJ2#(pu;t?-|kx#Hp5eWwe$~{kFT?iOaquK{WY%#g*r~=;} zboaHH;SffO8Mncf-D*E$3AhD3*>0gst|Si5ZW1GC25LqBg89xFc{yWJpYenQ^uh+g zho+^=4=;)Lw7a8AKH4NXJ2_7r*B*Q4;dauq4_7-(=bnh6;XO+AEH3H2))CHq=p845 z6B5d-s}a0a+p)EDd%-_f;Z6x)X>Fco*F<a7mVJ1CyjQdV+}BRk+jPIRjF>?fXLp#; zX`(^8FVhK6C5iVUA_9kNlP8J&^SD;LfTQ7GVm!Wc2lvb7-x3{n?*kdJ+}0jYzz$h+ z?^9=zmKDX_K5HyCAJ^U5@hBY6l7;B%TDO_7CCD4o+D;ZnQ$$yiL6@#{WPLifpb3Rb ze~a-qDs2h;!DRrwn5o|I(JRO^tFXiW0-0BD^1De!c_Ir*kt@jhMg<ZEZ*%}K=AdK2 ziAbj^<a_Fu;N5I675+WsYnZpf{nOEIixIqxruCG#EAYs!gcR_Ev^tpd%44fP0ctZX zVXE+%TSIC`Q2WK(MJ-H$w=RnITa!J>k8uMkrg*4M4nkDdR^*9zi`%-QV@~PFORl>_ zsbpbjO14{my=pNNKPJ;ow+RBdv>RKgRdx9<a6!?hi>dEG6C(MR8kfOo!Tt=s?3HuY zl7RQ0l!Z`od>G6$0C;P4W)ULGB6!8T{neuE=+W?8YbIv#&U))uR&^<Zay!-e*?WK9 zn~z#{o@Y0Bh6&cOIWss6o4jjajIa{CUcoRcIN2}XKf#tA4@KYVZuLM_6{_GyYjtP= zXs$y0`W#&*UqLXS!wyF*W!DX5+XD7(OV~+)YJ@6^vn47aNAJZr2e5ioLo4D0fgaDP zPyDAReHX4Iv<Z&9#sqIqX>2b2w@_#aBm})mRONXFKTc~oYQ<8?`+3E9`QdTx4ILQ! z2ZkI`KvPf|v;|E|(|HP*z34v?*BEL*`1%oX0>64;iq#Z4_v>IQB(X{)tA4fQyPs5T zo@+?`5kYO$;ljX5X@y0Lm=E7s3PAnP{hhk>)cF~tYMl&dA7(c9kCbFHXe1yPd3JBP zXXy;hYTa7jZdw}99gU7>%gB*VNw+QX{%(rB*wHfjRl_+WvP6>8ja2YANEW7s-krT% zw@PUYPwqAp4!#WDdjg2PE19qs)$(Iu`Nam&)?2kpaN*4h?g2s@+7Fb68t9RR*;=o4 zqjV^hwH0k#GO<D6jU_^$<wuKi#_m5<)~Rdb?S&V39rdT!9*flTn{`fpjPt#0O)%%@ z6L{9YN<ke4QQa=r!J?z^m<-c?DLD1tbuQ}DP-kf$0U8bn<L=FXf-uKADw9t3m7|A` zsXNY<OY+c!v}l%3zieB^W|=<E-g4{piV;xQ1o+;f`<qTo0`9BH-&{f;FfU7|vJlmb zg(@Jqnt)e^#wvqs!Ygk<t##oEsNFDFeVx36+M_8_Tlt=ezKz<Fh}2fWPiSi$zQt5} ziFr`5P{%KXc2uh99|l~6WH{N>!OHU0fIcdMKqDa#ySAERfMCoH*@YVN#cbBPY(b7p z11qv=fZ+y2)m5$BnNb--RLN~d70Nl9sq1~0fXJH+7thnVR9G=q^1*{-0tMYji2?p= zr&3xa55ui)?EQGBZ{<Eog=DP(QMD>ssGi_{1yX#qMI1B61Z}YqysI@@4ZEQ>?r8U{ zh6mk%O~fY8QzT~h#7Ite>1emLI$Cd}y3ShXZkbzX)GalttIPL{u$nezo$#?!#Dm`P zveOumH4iPpdcgW>DO?}=xF67ZG3m3bFmmEAeXjnM4=yQbOc|nmKfRBhYNDSOs4qg` zGJ=V!1jfNPS3g<KXcug$7*{fMnz5)3SJT<_W#3%pF&dNka=|QHZ>f)kT=X}|wF11I zRot5O?|&zY(CSZc-aO&C(GTLs;C%nL;Hy9St3P%zgMhd|!FxXPLC+gELMCdHVI1Q& zwVly`DV(8DUQ^%k-d~62Q|uHLcK$G-{3hy}jdUyud+L|u<4vomDpUHNO^1O{!uqrg zYw%?1;fa9?nG4H<s4-uxPiS`%k`GljOvnCLWH3g6+moLrXSrpgi1g<0z0HZaZ!9sW zI8rVc67F6AFH?Uo=}K>OJ45C_ES3s_z~u?cBT{Q;|Dm*hW>`p#Cc{{&VfDL2$ZhQ2 zIi?A1PytA9APA)qlutq!Dx}@c*Mb@pBou2EI!yWUJ*>v{Zea)cT(H*rp}0Svs4OE4 z>kquC5x4R0W^jIQeP1a{N9&>#lY$r<g4~<lu|9sM+zV1{{d*{l07;X1&yZcE_^g6Y zfBYq?wB%4N6lhE?S%R1N3X#S{B<j!wzmaqaPsTDnmmE3@5*&<FH04r|jrWYO{;kS6 z6}%S@(N@geocXqAlI~pv6EVkDUyxuAQ^?PF*xk7Uhdr*(*_8$#zjhSu&RPJa(hYw& zN%nj=nGTh<m-L<mfbdXQ<$NgkE#TsLzZ-;1Ht~gg`d*cr#G<cvl@adU6C`J}8gXc) zL+|Nf7Ufla_onU4YoNXHZrIpAD6}SI$MC%)M`<x1qWc-od77`xkB&-b|H$}m*@gw7 zc6GB!-#fTp!{Tf@P{TQx5-Ss44<lZN_Q!}}Et2)|#F@{cd1DOU(aRJ&L3z5Ls~<|_ z0u9G$S<lpmHAd+KgC8ee!C3371OLu4T8o>XA`WuOI9xmDU&{hqj)myMEhC#9Wxtl^ zP&-l?r1-a3vkI+PbqI|k3f^Ya$0sbN&>YE_gx+C+>O>8-1At=IVS#8`qO8sxD<R{j z5_3;!b%qt$tHw^W+qkUIhgUPRZ3Ej(N511%9^Od;PDbZ*?NwO(ar{9ICE*H<oZ3nq zmN(oV%3{5J8;arRJNiZ%Tu{1uj}ohjh=J~X5t$Diicgb~hFdiSY$#?2pu$(yrn$Fr zeq6ph+@7{)#ywybkRE(QhwP#tNWW<1D2t^RoC^E7zVAj6?UT3pi5<^LI!_j_W}}$D zAVZgGG5Z}jIXI=&C#*4Y^7MdIR_(C7&7oJa!a8+Nd`(Kw?z~=KXBqnm3&I%2UG2>_ z?V!Mape+-DIGA->=!JfWt!DDxbl!FO#rn>#fBcEbjR3qs$<O4wsAJJMfyh^^By7|9 zXOC`==5pHFvWfhWh<5&PER7cEFUYTG7l&#qHrZptSm2qL4I{n+mu4G{YW<pk0(rWq zx$}szGqedz9<Ssm*6;hzSczV`elK066c2)jrIF%7glM7dc^RN7>L_7&py}=_0o6fP z*<Vz_^bZAnX}IqV*07`-2bivOSR1_BG1YR$vfyarY8yM(<1kfeyz5wXIg%a{>6%&# z+R^bSsmY}P*tA{w=-VO7Y3194FI)bDh`co;$Adbecs774-eV!dmGC*uT9B+aG7>E@ zkoca)rAVljH*OiwR$K(6-Ifua{<9ON(WQA?6P`QfEwHog#q!K^8szU(l}lKjjz`B% z&@wo+z4dMR7KIwzIXtW@K{A$QtU9MN+$PG|83l$swb`IAo+2dyYUh>DGUpXDeeR?k zv-iA+*Ez8igvKU3Pl57<2f4w3o!5?)?&fQ1XZTCZy4v_LW2|s27`Nwm*=J}_o7YVQ z>RUef{l4;ok3P9Jk96W$Dzy5|5$b@qn>IK2WsL6#r!*ODLP_M8p*%k-;)Z{Ss4AP( z`ikQw<EVu_;jrTfri0#1wv!$r7lZFxVbWd{S5%2FRf#?D36iFERmi~W8?^i72_+d{ z#4i(I?g27d>E1r7@54^nwA4ahHU;;g21htg9GXo`QizI$Ix{3@&bhQm67S|C2yqF; z!bdpXjxx1j;@2*XjV=VS9_u2@*7Nr-?Dijd>~_Q$+MVH7f+m(p``6EY_MWT&cnTcY zh8{=0XbzK()c%*6K>2IBaDkgt>b0_@32AcKgCmd7)^s)+yx`E9AxJXo$%%nuo=co> zIeu|r#k5<ZN0a3I%Mzw#oOqOZVl0pr8lB=qW6zhOwyBV^R@Hki>F8c7w0Ts*-*Xgh zHty$0*o0*7Z^O|G2P>5R-ifKCHNQgl>_}<Lt&jf5kD;=4tmF9WpCT`7@J&j6-ST@@ zz(+pC^u`W=m$32PX~Vk~Rv-wM$6b9ckDf%m^0Iq6W@3ciW}1?Tqv?2kv=V)Mm5%Rb z%OnRTQ0%v6F)oL4ogA4QT5N3VFv!XHe3V%#u|4};c>A0O3G`3)w~BSNSbzUBa0HG2 z%9LAb8H*W`WpU(H0&)zH&t(4<NYGM}%WBf!Y4w+{x=cz5JpYX7`vDQ^gC(`Wq4Xb; zD7#mAZD*(&ZHKKR-E*FfHiXc~ytdhv#WrX&-+d0Y6*OZ0m4SNcCCu-FX%THGY|>0x z>R-tYirW*U$yCRu-So7fsA-yJ3_IO@;Ekgzv;#6~8pv<(0bT<?0L-QvKR>j|^LUfB z>Y!=P{F~jsk+1g6C#P>F(MtR=f&&K*L>w{b&~$#6<Oa}xp9vZcX-gWX)y~(RS<n<` zsqK;8^1L=xm;<KMEukVMy;hSmG-DDgu}P=r_I_;sRpkGQd7%-Z9ej@Ed<Ou@lBn1k z0)~f}gX*x6d?R@Iv*Jc?ql`l2Z>uzXO+O=jrkr0EMDcu+70u{b+{8PiBPI+<2nS2a zWP|wU-l}Go^8_0sQ5XOvix$<OI&7Z@Ecg;{lJ<;(+rlu00pldR6mwLwXlX;%m_QC} zL1FawAwG`B%DYSM&*JP`MSG^)ES~?U8y2z%bP2`h=edDV`jg*$-TB=un{(Tsv+)*> zFcno8y(TrQjTc(RSIEircEiPCO&fP<Gque_nq>4f@CBf{e7F^S!&0U?7Q|&X28F$e z6C?u|{wT%%PV4A-Q;M&&9zHbAd}EBI=75z)338s^TZ-4g($j~QbS^_qkN5`h^P3b6 zC=bW)r|B?0*O?T;OAj<a++Z;TuWQkYji4V;T@*_}YzIJp<2uHBV6>a21bdb8^i`Q> z+F6xBaO3`*_$Yn3gw}JQ`PzU-pM2Y)I#&{~D^aPWgsU{;y@IfKHvNxsD}Z6Kg<*Px zop>XU1W3CnjkZ%8TVAKR1;<GpZVN^;Qqx35HCe>pc@Bh7%{KN;wQ{V;0<vDMTU9`b z!jykOnW+DvWC1YbhE^rQ<`kNz5~xTkZ&wXbZ1I%aTsozyp~hRy97XZ`E`{IDbh<mI zzKwDsg}#At#p<0wGP5V8)+|xwEL#L{!#}m~x(b5<Ij4&(;uymR+2j3%jo%JpaLc{3 zm-FL&-&m8SBPT(<yd#^O&Mo@a@ig9&6?tQkNSwm;k{Yr3`wmqJq(6+YQh7ZfF$$3i z_D<|La`dK%t;dF0Dom-rVE(z(+hQyHbIFWWt{sYYz`GI|tyJ6^v1+xQC|Pv#2o&cA z4h;Mt3}pLHD_(leX37dD=Ar6DJJN9T-@R=Oe1fi!#p)89v>Y7o>*l#|bf5x=+5_2) z&p^c<b?F^nMhcDgD*1U)@eU)4LYcP5ZbbRU59tk(xfZUPnHcb>P4w<FoMEymYt<x1 zvG>w+xmZc+N^nOjE?F}nXrpzm-)d!V>cWvV%gRRQQoc(|El*H)wOqN&34MBshet&q zMG?m|(m1kPgQ1!J(I0|490YxNA3w!CYqLZC1W)hbA3y$!|CUKBSbNw1rgORt<=_8n zNTNse?k)VlzxuSe_9zJ$w?cRk6h^djs2<v~6}v4ZLkU=4*J^u)t$_0srS$O`3U1Pc zd%FM!cgI*abcrPOULom8dE>inm!fB9?YUF-gfAvD5S8H`j<2NEBtoGtnn*aj2aSus zi)JzH+HBG&@OTAz3i5-Y!T%=0MJ|A1lLLB)ts+KE`S>)nxu<pCXq0#o@Fqs<?Z^X3 zZC_ILD0<LFq1#vcQ*^|~3vB3kqDSsJgGSl#D&YyE)*+r3Nhq!i3Zx+hqvZ5U4rokn zA1DHSx`$l;$f@k{7*1>X;Sl7t>l6WAE{z6LkEc(QzrbC$?ZL>adPVcLQ`JMf%jO|c z60T@EGH>Q~yVc9zd<O$EU(%U5F{-U!R@1_96bWV)aAXq$Zhll4@+VJL%togQLxTwZ zE(K~;wtVu7;Mtw3?xZa|x|;E!X~dSMD%5A~Xiv-4oo1!9g+kr>(ET$&j$`%wxAu+J z<>lL*)qWcZTR?Dm6r<IHCKuhp9n?-slEN4{ZNc#bGGGpXE5Q-x7aY5%X??r?Li%cL z%WbmQqc;C4?o2l;^5la?S9_I+?zLWDc#~TDr=s|0bx$HISb*X>>g8!9UG310h}x{7 zTVr+kwo89A1<s}dES@1Jn_VBPvr(3lKkzMGp>LM^ZHC&en&v__`Vti~-o@^!#Hyp* z&*vI_@$;9#P0kAlB^5utB4GC`{0L1jVJGk3HYZAhvOu-D_^H8g$NY=T`>#M`*JGb2 z!V9(1@4a!ShW-lg3~iCUZpxt*jSM{5GVR8{hUHG3`Y>se{I$Uhy5Mo)ciU7llatNK z?Ub`xvQ2_4T@*r0Opv~ooEsm{?~VJmDpyv*rMk+$rq_YMm9YylYGGNp-Ga`a&f)O> zj$=U{A3lng%^bCcy*)9z)QWHJt&Gn06pd=ezsT)5Bd~Lat<Y8L8GNh@?lE}ClM$li zbNvlx0v+U8sLi}9k4~XEyN1v27MZY$cMQQ&3mm~*iJ_tLES2AuwH2IcFVg!F*v}|_ x4ohz;tLPpKrHwUvFsWkTd$x70YzUXH`@h}H|JU(+PnY{agiExS1F{4L`X41RqG|vD literal 15660 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 diff --git a/gui/views/inv_bgp_peer.py b/gui/views/inv_bgp_peer.py index f67054c..7f2153a 100644 --- a/gui/views/inv_bgp_peer.py +++ b/gui/views/inv_bgp_peer.py @@ -2,15 +2,11 @@ # -*- coding: utf-8 -*- from cmk.gui.i18n import _ -from cmk.gui.plugins.views.utils import ( - inventory_displayhints, -) from cmk.gui.plugins.visuals.inventory import ( FilterInvtableAdminStatus, FilterInvtableTimestampAsAge, - FilterInvBool, ) -from cmk.gui.plugins.views.inventory import declare_invtable_view +from cmk.gui.views.inventory.registry import inventory_displayhints inventory_displayhints.update({ '.networking.bgp_peers:': { @@ -54,5 +50,3 @@ inventory_displayhints.update({ 'filter': FilterInvtableTimestampAsAge, }, }) - -declare_invtable_view('invbgppeer', '.networking.bgp_peers:', _('BGP peers'), _('BGP peers')) diff --git a/gui/wato/check_parameters/bgp_peer.py b/gui/wato/check_parameters/bgp_peer.py new file mode 100644 index 0000000..bcfff4f --- /dev/null +++ b/gui/wato/check_parameters/bgp_peer.py @@ -0,0 +1,255 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2017-12-25 +# +# Check_MK bgp_peers WATO plugin +# +# 2021-03-27: rewrite for CMK 2.0 +# 2021-08-21: modified for bgp_peer plugin (from cisco_bgp_peer) +# 2021-08-29: removed htmloutput and infotext_values option +# 2022-04-02: added bgp neighbour states +# 2022-04-29: added upper/lower prefix limit +# 2022-05-09: added discovery rule set +# 2022-05-11: added remote_as to build_item +# 2022-09-05: added internal_item to avoid warnings on cmk updates (THX to Jay2k1 for reporting the issue) +# 2023-06-11: moved wato file from ~local/lib/check_mk/gui/plugins/wato +# to ~/local/lib/check_mk/gui/plugins/wato/check_parameters to override the build in wato plugin +# +# Known issue: the override of the build in wato plugin will break the build in aritsa bgp peer plugin + +from cmk.gui.i18n import _ +from cmk.gui.valuespec import ( + Dictionary, + Integer, + TextAscii, + ListOf, + Tuple, + TextUnicode, + MonitoringState, + ListChoice, + TextInput, +) + +from cmk.gui.plugins.wato.utils import ( + CheckParameterRulespecWithItem, + rulespec_registry, + RulespecGroupCheckParametersNetworking, + HostRulespec, + RulespecGroupCheckParametersDiscovery, +) + + +def _parameter_valuespec_bgp_peer(): + return Dictionary( + elements=[ + ('minuptime', + Tuple( + title=_('Minimum uptime for peer'), + orientation='horizontal', + help=_('Set the time in seconds, a peer must be up before the peer is considered sable.'), + elements=[ + Integer(title=_('Warning below'), unit='seconds', default_value=7200, minvalue=0), + Integer(title=_('Critical below'), unit='seconds', default_value=3600, minvalue=0) + ], + )), + ('accepted_prefixes_upper_levels', + Tuple( + title=_('Accepted prefixes upper levels'), + help=_('The values from WATO are preferred to the values from the device.'), + orientation='horizontal', + elements=[ + Integer(title=_('Warning at'), minvalue=0, unit=_('prefixes'), size=5), + Integer(title=_('Critical at'), minvalue=0, unit=_('prefixes'), size=5), + ], + )), + ('accepted_prefixes_lower_levels', + Tuple( + title=_('Accepted prefixes lower levels'), + orientation='horizontal', + elements=[ + Integer(title=_('Warning below'), minvalue=0, unit=_('prefixes'), size=5), + Integer(title=_('Critical below'), minvalue=0, unit=_('prefixes'), size=5), + ], + )), + ('peernotfound', + MonitoringState( + default_value=2, + title=_('State if peer is no not found.'), + help=_('Default monitoring state if the peer is not found in the SNMP data') + )), + ('admindown', + MonitoringState( + default_value=1, + title=_('State if peer is admin shutdown.'), + help=_('Monitoring state if the peer is admin shutdown') + )), + ('neighborstate', + Dictionary( + title=_('State to report for BGP neighbor state'), + help=_('Map each BGP state to a CheckMK monitoring state'), + elements=[ + ('1', + MonitoringState( + title=_('1 - idle'), + help=_( + 'This is the first stage of the BGP FSM. BGP detects a start event, tries to initiate a ' + 'TCP connection to the BGP peer, and also listens for a new connect from a peer router. ' + 'If an error causes BGP to go back to the Idle state for a second time, the ' + 'ConnectRetryTimer is set to 60 seconds and must decrement to zero before the connection ' + 'is initiated again. Further failures to leave the Idle state result in the ' + 'ConnectRetryTimer doubling in length from the previous time. ' + 'Default monitoring state is "CRIT"'), + default_value=2, + )), + ('2', + MonitoringState( + title=_('2 - connect'), + help=_( + 'In this state, BGP initiates the TCP connection. If the 3-way TCP handshake completes, ' + 'the established BGP Session BGP process resets the ConnectRetryTimer and sends the Open ' + 'message to the neighbor, and then changes to the OpenSent State.' + 'Default monitoring state is "WARN"'), + default_value=1, + )), + ('3', + MonitoringState( + title=_('3 - active'), + help=_('In this state, BGP starts a new 3-way TCP handshake. If a connection is established, ' + 'an Open message is sent, the Hold Timer is set to 4 minutes, and the state moves to ' + 'OpenSent. If this attempt for TCP connection fails, the state moves back to the Connect ' + 'state and resets the ConnectRetryTimer. ' + 'Default monitoring state is "WARN"'), + default_value=1, + )), + ('4', + MonitoringState( + title=_('4 - opensent'), + help=_( + 'In this state, an Open message has been sent from the originating router and is awaiting ' + 'an Open message from the other router. After the originating router receives the OPEN ' + 'message from the other router, both OPEN messages are checked for errors. If the Open ' + 'messages do not have any errors, the Hold Time is negotiated (using the lower value), ' + 'and a KEEPALIVE message is sent (assuming the value is not set to zero). The connection ' + 'state is then moved to OpenConfirm. If an error is found in the OPEN message, a ' + 'Notification message is sent, and the state is moved back to Idle.' + ' Default monitoring state is "WARN"'), + default_value=1, + )), + ('5', + MonitoringState( + title=_('5 - openconfirm'), + help=_('In this state, BGP waits for a Keepalive or Notification message. Upon receipt of a ' + 'neighbor’s Keepalive, the state is moved to Established. If the hold timer expires, a ' + 'stop event occurs, or a Notification message is received, and the state is moved to ' + 'Idle. ' + 'Default monitoring state is "WARN"'), + default_value=1, + )), + ('6', + MonitoringState( + title=_('6 - established'), + help=_( + 'In this state, the BGP session is established. BGP neighbors exchange routes via Update ' + 'messages. As Update and Keepalive messages are received, the Hold Timer is reset. If the ' + 'Hold Timer expires, an error is detected and BGP moves the neighbor back to the Idle ' + 'state. ' + 'Default monitoring state is "OK"'), + default_value=0, + )), + ])), + ('noprefixlimit', + MonitoringState( + default_value=1, + title=_('State if no admin prefix limit/warn threshold is configured.'), + help=_('The admin prefix limit and warn threshold needs to be configured on the device. ' + 'For example: "neighbor 172.17.10.10 maximum-prefix 10000 80". The threshold is in percentage ' + 'of the prefix limit.') + )), + ('peer_list', + ListOf( + Tuple( + orientation='horizontal', + elements=[ + TextUnicode( + title=_('BGP Peer'), + help=_('The configured value must match a BGP item reported by the monitored ' + 'device. For example: "10.194.115.98" or "2A10:1CD0:1020:135::20 IPv6 Unicast"'), + allow_empty=False, + size=50, + ), + TextUnicode( + title=_('BGP Peer Alias'), + help=_('You can configure an individual alias here for the BGP peer matching ' + 'the text configured in the "BGP Peer IP-address" field. The alias will ' + 'be shown in the check info'), + size=50, + ), + MonitoringState( + default_value=2, + title=_('State if not found'), + help=_('You can configure an individual state if the BGP peer matching the text ' + 'configured in the "BGP Peer IP-address" field is not found') + ), + ]), + add_label=_('Add BGP peer'), + movable=False, + title=_('BGP Peers'), + )), + ('internal_item', # added by plugin discovery function + TextUnicode()), + ], + hidden_keys=['internal_item'], + ) + + +rulespec_registry.register( + CheckParameterRulespecWithItem( + check_group_name='bgp_peer', + group=RulespecGroupCheckParametersNetworking, + item_spec=lambda: TextInput(title=_('BGP peer'), ), + match_type='dict', + parameter_valuespec=_parameter_valuespec_bgp_peer, + title=lambda: _('BGP peer'), + )) + + +def _valuespec_discovery_bgp_peer(): + item_parts = [ + # ('remote_address', 'Peer remote address'), + ('remote_as', 'Remote AS'), + ('address_family', 'Address family'), + ('routing_instance', 'Routing instance/VRF'), + + ] + return Dictionary( + title=_('BGP peer'), + elements=[ + ('build_item', + ListChoice( + title=_('Information not to use in the item name'), + help=_( + 'The Peer remote address is always used as the item name. By default the check will add the ' + 'address-family and the routing instance/VRF if available. You can decide to not use these ' + 'additional information in the item name. Do so only if your peers have only one address-' + 'family configured and you don\'t have the same peer remote address in different routing ' + 'instances/VRFs configured.' + ), + choices=item_parts, + default_value=['remote_as'], + )), + ], + ) + + +rulespec_registry.register( + HostRulespec( + group=RulespecGroupCheckParametersDiscovery, + match_type='dict', + name='discovery_bgp_peer', + valuespec=_valuespec_discovery_bgp_peer, + )) diff --git a/gui/wato/check_parameters/inv_bgp_peer.py b/gui/wato/check_parameters/inv_bgp_peer.py new file mode 100644 index 0000000..f4832c6 --- /dev/null +++ b/gui/wato/check_parameters/inv_bgp_peer.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2022-04-24 +# +# 2022-04-24: added option for BGP down time +# added option to remove some columns from inventory +# 2022-04-28: added Whois options + +from cmk.gui.i18n import _ +from cmk.gui.plugins.wato.utils import ( + HostRulespec, + rulespec_registry, +) +from cmk.gui.valuespec import ( + Dictionary, + ListChoice, + Age, + DropdownChoice, + Integer, +) + +from cmk.gui.plugins.wato.inventory import ( + RulespecGroupInventory, +) + + +def _valuespec_inv_bgp_peer(): + removecolumns = [ + # ('remote_as', 'Remote AS'), + # ('remote_id', 'Remote ID'), + # ('local_addr', 'Local address'), + # ('local_as', 'Local AS'), + # ('local_id', 'Local ID'), + ('address_family', 'Address family'), + ('last_error', 'Last error'), + ('last_error_code', 'Last error code'), + # ('prev_state', 'Previous state'), + ('as_name', 'Remote AS name'), + ('as_org_name', 'Remote AS Org Name'), + ('bgp_type', 'Type'), + ('version', 'Version'), + ] + + return Dictionary( + title=_('BGP peer'), + elements=[ + ('not_in_service_time', + Age( + title=_('Time peer is not up until considered not in service'), + default_value=2592000, # 30 days in seconds, + )), + ('remove_columns', + ListChoice( + title=_('List of columns to remove'), + help=_('Information to remove from inventory'), + choices=removecolumns, + default_value=[], + )), + ('whois_enable', + Dictionary( + title=_('Add whois data to the inventory'), + help=_( + 'The whois data will be fetched via RDAP from the registries. For this the the plugin tries to' + 'find the best registry via the RDAP bootstrap data from https://data.iana.org/rdap/asn.json.' + 'The query it self will go to the found registry via http(s). Note: the request might be get ' + 'redirected if there a different authoritative registry for the ASn' + ), + elements=[ + ('whois_rir', + DropdownChoice( + title='Preferred RIR to fetch whois data', + help=_( + 'This registry will be used if the plugin can not determine the authoritative registry ' + 'based on the bootstrap data.' + ), + choices=[ + ('afrinic', _('AFRINIC (https://rdap.afrinic.net/rdap)')), + ('apnic', _('APNIC (https://rdap.apnic.net)')), + ('arin', _('ARIN (https://rdap.arin.net/registry)')), + ('ripe', _('RIPE (https://rdap.db.ripe.net)')), + ('lacnic', _('LACNIC (https://rdap.apnic.net)')), + ] + )), + ('whois_timeout', + Integer( + title='Timeout for connections to RIRs', + help=_('The connection timeout for each whois request.'), + default_value=5, + minvalue=1, + unit=_('seconds'), + )), + ] + )), + ], + ) + + +rulespec_registry.register( + HostRulespec( + group=RulespecGroupInventory, + match_type='dict', + name='inv_parameters:inv_bgp_peer', + valuespec=_valuespec_inv_bgp_peer, + )) diff --git a/packages/bgp_peer b/packages/bgp_peer index 99a8b76..f7c7031 100644 --- a/packages/bgp_peer +++ b/packages/bgp_peer @@ -15,11 +15,11 @@ 'checkman': ['bgp_peer'], 'gui': ['metrics/bgp_peer.py', 'views/inv_bgp_peer.py', - 'wato/bgp_peer.py', - 'wato/inv_bgp_peer.py']}, + 'wato/check_parameters/bgp_peer.py', + 'wato/check_parameters/inv_bgp_peer.py']}, 'name': 'bgp_peer', 'title': 'BGP Peer', - 'version': '2.0.1-20230611', - 'version.min_required': '2.1.0b1', + 'version': '2.2.1-20230612', + 'version.min_required': '2.2.0b1', 'version.packaged': '2.2.0p2', - 'version.usable_until': '2.2.0b1'} + 'version.usable_until': None} -- GitLab