From 628df021896fa8775f9743af62a4267b617cc35c Mon Sep 17 00:00:00 2001 From: lavado Date: Sat, 30 Nov 2019 03:15:09 +0100 Subject: [PATCH] Revert "Migrates alarms to MongoDB" This reverts commit b6233b3d90ca1ba617e476b915fba056cf7891f7. Change-Id: I82b7c5916cdf7eb2816348c4ea13609d0fddffe6 Signed-off-by: lavado --- docs/architecture.md | 2 +- docs/assets/MON_Evaluator_Evaluate_Alarm.jpg | Bin 18213 -> 17581 bytes docs/assets/MON_Overview_Diagram.jpg | Bin 35633 -> 34487 bytes docs/assets/MON_Server_Create_Alarm.jpg | Bin 21462 -> 20229 bytes osm_mon/cmd/mon_collector.py | 8 +- osm_mon/cmd/mon_evaluator.py | 8 +- osm_mon/cmd/mon_server.py | 8 +- osm_mon/core/common_db.py | 16 --- osm_mon/core/database.py | 96 ++++++++++++++++++ osm_mon/core/models.py | 61 ----------- osm_mon/evaluator/evaluator.py | 2 +- osm_mon/evaluator/service.py | 43 +++++--- osm_mon/migrations/002_add_alarm_tags.py | 70 +++++++++++++ .../migrations/003_rename_monitoring_param.py | 61 +++++++++++ osm_mon/migrations/004_remove_alarm_fields.py | 64 ++++++++++++ osm_mon/migrations/__init__.py | 23 +++++ osm_mon/migrations/conf.py | 26 +++++ osm_mon/server/service.py | 39 +++++-- .../tests/unit/core/test_common_db_client.py | 35 ------- .../tests/unit/evaluator/test_evaluator.py | 3 +- .../unit/evaluator/test_evaluator_service.py | 25 +++-- 21 files changed, 438 insertions(+), 152 deletions(-) create mode 100644 osm_mon/core/database.py delete mode 100644 osm_mon/core/models.py create mode 100644 osm_mon/migrations/002_add_alarm_tags.py create mode 100644 osm_mon/migrations/003_rename_monitoring_param.py create mode 100644 osm_mon/migrations/004_remove_alarm_fields.py create mode 100644 osm_mon/migrations/__init__.py create mode 100644 osm_mon/migrations/conf.py diff --git a/docs/architecture.md b/docs/architecture.md index cec6697..8e90ab9 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -50,7 +50,7 @@ MON Server subscribes to the message bus and waits for the following messages: It performs the corresponding action and sends a response through a unique topic made of 'alarm_response_' plus a correlation_id, which is a field contained in the request message. -Alarms are stored in MON database in the OSM MongoDB engine. +Alarms are stored in MON database in the OSM MySQL engine. ## MON Collector diff --git a/docs/assets/MON_Evaluator_Evaluate_Alarm.jpg b/docs/assets/MON_Evaluator_Evaluate_Alarm.jpg index 0e2e6763c6338509c098a622b9c260306cc9fc62..930380f6ba54874f233073d23c443c457ce0967b 100644 GIT binary patch delta 11194 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 bO$qc}8GK$KavO50r{oW{s+JfrTIBx$MmEy? diff --git a/docs/assets/MON_Overview_Diagram.jpg b/docs/assets/MON_Overview_Diagram.jpg index e6f8b783c6ca0fc874343535fa8661f56ef0c375..c804347a1256c0bfdcd77626a488df107dfabd27 100644 GIT binary patch delta 21050 zcmcG#1yr2NvM@RjNP>po?(XiEFt|Gm?(Q0FfZ&n+av|E=}jtZ$~Pt4q47y}q8xcWjmj$ZJo*^a*(J#`HMjp;2iRXpLPKHN{jJ*7{dY*&Y0JHh|})L3=v z`}&<^vu>8zGt8_0;it0K+bKU^xma1-pF2I}poXd@9LKTH{Lyjsc)r*7xq|hdu>VQa z`_WU(PvY^dsMl+}gt1RV|Ev`>bX`Q~aM*~AZL5`Pz4)Y1#y{m`x;jeiJR9@-10!qm z&E3-qcQd#=Vf#-c0GrgTL5I&o={EwZL=4nmqwQMW-PheWaLRJZvdaG|=1k<9hd1yZ zcu(XYGf6 z0Avl36>@}#2qgqTN1{T0%fiYD#3ZKVB4Jm+qJT&u&4cgb9s%gS{XPA2@v(-O0!a=_ zVa*ofKGcnzlz`-s4Si#AiqJ4xiD>o=R62#>3Bn8eX-F_WKb@iFb#jlxqC^ z4V~cw5BGdzytev_h;{4@OErp>JcB^5#i7YJr0g;E#ChCcBbR@>Co z+C--p`+++*IlQbcx?DdSGEGh{Fw}e%-*6qxccjtE${@`+ObDE}`?ygnH&Ly~AjI4w zTSh{XHX02DFlC>sxMjFi&cD9hytiAdaV>+sLOAHJPJIOQU~to9CkvWz&vEAonW`ha zt#%^{i@mQ{&YlZDJKH4gPIQ%H|6m^wjLqF!XQTCca@_vC2oKv!`cvu#7P**YUj$e~|pG0K;TN^fsw&pU9{-w3G>>gYtY|Z^38<4DL*M=)B-l?a_%xGvlsq zn6j(s6TIDJVOB)66fKpgEyS!P1<&MwroutdR!R)dxEglIDAvR?8_&=AZ{CmvBRww{ zGCn)Ww4I5BF@vSycAi4w)*zP)uUCc_X87Ia4d2z#O!cNB4w_5iFa~JgShDt`hBMa( zu_!*VV{X0oU=$SoAbiQT%&VD3;&Ll$QLJG#XGUahwES_t-+w6)56st#@5#M0B3%iK z^A?Os<*N7y7#JWgEZ$layLDr4>j?YQRfkbMR?Ee<%%$<6Y&Mz4Nu1Gqa|FLJJAvJC z>yte4>Ce-DV6?}Fl6j!dB@xnCFaJgK8}*xywnOPS)5$mZPk!*Hf0a>=Fa{n%Xx8@r zEcvs5(fkJra$o;Hwf<%jZ*vf~O?psG5OZCgSCKVcwZEzk$}^wpZf4^g99thjTnt< zhbII@evcNg1!8W&en?4SW|iSdLYY8BYYd4&m0DiLT23Jg)@0BD%v1eF++Nrm!nPN! zs@l^wU}(da!Ky8%7;5ID9ou}{kt<6cxT^Ak!sh1r$z{KQHnVz9#wkYT4Iso;$ z@TryYKgH#iR>rvt$+F=|2ET~0pY#Af83dl`&pu4(UnIB~oFBUmO!yV?2p|H(-74q# zOa%0O>@>6q?Yk6n{SFbBbZA#oB8F-twhH7t^PVdSh_gTf8J8N&R3`jZBmY@xF6i@w zVR_dAWx~3nS=A4sFy|89*{ad>pN9$O!NJ8mFjE{RX>Qo;WDDIkrpQLvb$W#0kC7$( z;&O>QNp-3KSAkFJ&So~6_`d>(8I85am17Q#Q5w;L(gU}!eiR^PEpCX%4H)Ct)@v`A zHQ8eA?9FbXEhL?L2R|!l4bk_>{Yqx09G%3pojtpqJ*9UQp&Vs2_ECBBn05W@17!`^ z{1{UQEAopjBlcuG@648G-WIc6woEq$U+l}}OZeBC0YE>op2p?a=gTF5x9;U7UDwicPVe(IY@8OkFJ8{lywf=XV)}O~O2uRkOI6iCYW*UQLIJ z^?tV7=YAn`Q?5U5hekj+rQvVX{*jIafWHaVy^+ijJtV^i6a?8f z)ak@T;%alJI%}9AfIG8>C@Y~Y3?uc8eowMeUBR5}wj@ND+Mg(h$TjTO#rqz7!-@kt z5Ut%cfYu*auU6UIdfvTxqkQ~&{sjOwah$L-n}AmLHBaxlLwn{ILTU&3Wuyf*SEewE z;C+gKVS-_f9PXN6%&7GVe2_@Ego6b#14+*_3gy@f73_v^cE0!9gs)wvmqRz-d+}-n zdjhHhguEnaA^JM9#uz33wNYwS@H6i~{dAhJR>Y;xsKglb1g`(UOTTRfD9EWZAOBLH zGv>U+G&x&7NL9lgPOSoZ1`5<}rH*5{QL61y{OK>=!fWgkjrkvVP^JqF@B?r0)t03T4|W(n$f>8c zI$ka{V(wDcbYN6=YHC^6jm-a|aG1}H2Q7c0U6hVHUT>%{mqPk{f;8?ptML^ULW{!= z{t7!+#vg5s9gcuES4YQGrc}oS#mV%xMtdMUnKnG#F2s7rwKvstbRi2kH*2m&?6 z%yPgrRX&h|i=a~5!EOK3o<#J<11LApFC8G6_ zc1M-_7XPiAQTC$V-B-T)vz$NlogIy?@kD4c0`a>)Dr<4y>TQT0U%Q7=Iz&lkW;$p7 zApt9#`<){8RaDog5r}LbnNa#uWr&JrlafwTI*s1NjYHIMj{w!D6=H2pPJX^&>pN2% zAAq<41GpooX+bG|GWU7Y^-IetZA*5@oIp^SOEKT3DPeM%_tsj8awsMIf+=F0a|T^B zyQn8xG#^KFkU(@WtwC)3UyH7ngf7)=ci@)#?*+J%wK!hDF<8~2SJfh5+WcH45C<6# z+Rl-ji%!E-E!uGs9`qr;OyzutumML*@lO$wPa;ABk12lV^`IeJcw}Ix7tpT&P_Td( zP=9Re-$J9JyID>(5EKO#=@0GjXh%lT{>J|s zP-^pkAoFm!_IU%A_mP!tgVRe`J-hrdwRjYF?S>jnLnKEd?N9R{DpPpI{)|qVG><(a zE5V+df)Bd6<+ygEz7hJC9WZ%^p^S%4eWUdddsT(1tPYodMXPX|?0I5oGkh~iK|m2} zy}QBLNvm)lcGn#1%|ClX!T55mQ!Kwr-Ut1vs(kt;8vH(9X9ksnzxg-Ui1?9UY=^kY zEWEnn!uL&Ym0OH!H#9$PsvS?fXzn#3n1#8tD&5|njrnbqc}oNBONU)#jGjkn(fjI~ zR{{dp9GrI)Ds@A&^aWK}gW>--3HZN~X2qxLN=^Om+-*B8A^j2mc=C$dG6Zftv>pM% zp2wfFlxVdWjCuSDHgem}UbW$RAz7;}{d>1~q6tfPq>cUBzj2CmEy(OKPid@KOe4fVp zGzzV$@R0L*l!0SP7xEJqJ<1}Ew8=zDTa@2+tz6E9(XWpU3i)+%Ye2RYrd?UOwpIerE??gdM z%eVvUc|5Ul^I|3bLrwjI@00q&d)+^4i?%!PuS#cm&#GWyv1;;%o*i;ZGn#Z32ley} zrv+4b^H3zPt{=+f--IWD9UL4PpAC(hdp7lXUS(u7Zd@y@bb11w=GbR!GwQP!p66RE zEYy46yVl$`B-u71y#!lSrP1`)xy~kSMSS5txGAnv-nhAN)bZR`98%j_GYA&mSgm>q zHmb)_5E;+(7Vp|8zUDYD38@n!L+YLvm z7e&$odlV1np10CIxMAu)7(`A&Ef3ROjmJZaRq|4I9s$+fg;Di=M!nJ!`d6=Pa#fsTvoo;Z=T z{O9b#ded|!$qRm>zvWOY@O{l2^t#affBXD5vkqT~AqADJ5OrG8nc;K(3cW0+?tu zwf1DZTk;A=ty_lFR8Us7nf)4r#_VW5zv8lB;}KBxNr-G;%gdwLC07=Ov~%Xt_(ROf zpbv;U^u7P`kk-*Wp>h35Iz-uaL=gBPx{v`Z`jyyu(2rX2M6jn`Di!{)O1l$7PbRB4 zP(5g#L$ImYCHr%3e&6`iVzqoi4(=`HGH#3xUpPcaqlH58M$fct*?gU@=mb1pEk)@J z4JP`eWgjSHJaw0K*sI=uv6I`@`*T|^k8=wpe_t;DNAq#aZcM_VV&8`IeU_Fi>zB{p zdg^Hp${LNnv>V{~rD+VV+2*@&9ebgu&bh=12_iC;8BBllABs)MvF*t z(zFmpTUDi0XWy8luX>UwMK4rvPp(dMgk9~aJT84mY|`FvuW163Yk)11iUCcNBGS?H zQmheJv3e~PZcSjVyxx{dFRfySEn z2E1Wxuyc+if3Z3Wli4UYzXf9kA2(X7XB$f0803K-AIyGA&*5U59>BKdjkl(&C${*y z*)1P#>%6z8t5-4@zGv)#*%Lu&O*$F{A!C&WdRz&sV=s$%E(sK$49w!w)f0LI^iyrx z^P5JJOw>87-DjHFehx?wRn@A=VPl5{83KLxc;s z|GLeb4vIM@A)<4S^>v+MS{Y_nf_zl)VEfmu_C4A-5sVHrCq!NtMGZRX&MMm2gcwHHEJkq*aP^tdBccn|VloAT6DkcM&JhXSWiv?3Yp_WY! zN3Pdhi-(_!b&TBWxtc&f<ps^5pZ{V2hYGVRvKT8Wx>wkjzq~2@?B<6DUE^wBF8LIJ z5n!QU7PVNzn`|ZNcz8%dSTkcU?|RrcvMNftbbq@n`lYp+v~xb8b*5OG+iGOjU-io@ z{YVIZ@v zp#veise<0CqHz^frBHvIWW%DNE^G9dIJp-tZNb!yD_vZ_@?jiJO}Z_7mvN891LR^) zC6?xgvJoBuj{b!oZDMzWt5pYJ+`zXQutzCbzdjgLB{^Pv;*NX?3yN8nLHSWLwY;;s zjI{j}IYo;Y2E`|=Aa_utF9^oG8aFN}TrqEm!Ap*Fyy;4b$)zi17#E74S<03aD~rx9 zDD2T$F)VpulN$w7MV%_yZrgUWiN$qgdOx)aLH%@S$61H~7^Nj~3lV3R6c@2a@?CKbk z9|8V_FIIcvW=`J(EW4MZ*N7ZY2(Zu!*)I|O)X}sJy{pw$;e=7_f)TY)hepl+ekyj$ zl%#uRS9KkC_!kKN8~i6IEr%mre6s$2URNEqNd4eLws*pCxd+$0*Wl&tBmiRXU>!GA}ivC4hzue+i~{Ya}1HhespOO&WVcYKp>hSD9HyI4 zv^z+7HFy(G zy?8aAuNXA=Zcq3%U6maq7h=jz1I{J}FW9x>ym*-O-tH&5NI4XtbSz^9P$;ny#q2iE zHXkGS4xE$BqX{_J;~>}i;9SM%a9pbUNxDGIqp{^y5le9rxzC~s=kyMG=*Jrx&*C;{ zLpz*HWs6-;CJqucvZDJn5YUG1b^diJ5kwOoVG33T2^ll1pD;3X!62i2aBQ3}}vAw6vfDzi)>FsWCbi z)#OzN2?y$opf(#n`5XMNJrJrJO|SZ`aMnt(uc~E8dX4mwvx&^IETo_T%DgD_R^%js zajVe^a@2fTizZ!yK^|al&_Yx`J6$YgfiU7NQy9`UB5w0gZhSgV^!G*#vvbHJrp-j$A`zT-I70?PH7vN%1_s4PBTH?yU-o15ORXp^OHmnGsYEo)l6)0` z*nH)FO}!ro1={;_ zszzvvtmZ{)&7f~uSsno@I`S4|4+TwW6To~Wg5=}{!wE$jKmTvOjY{MTO=wWgznr@Y z+S{ZV{TOM%Cp}BMIQyaOR&XrjQU~18>aVP|rCTP9%ea?1sTPb=b^Dup@i@OGu+ln2 zX8LkY!&OOzar$x&-)f-Lb(TJV z(WjVC6}7*_^bLHIq{`eSEAy2;r2xoTsi0IG1Q*H!&T$!+R#Q>2cg%I@;G;e`gPFpD z&V}Qy=pK^c^WrhA_ys#xPOj^6G&3FUD%InmlEYe!tULbmZB$1@0_uCoN?yvFRrIWH zjR~k%C*BgSz%gw_7dtG`B(+@A5kJ&~T0a41!G#7YYPs6nl^yjote<${RILMnt@o^+xZj`{ zXs@&NKGw!ol<847#|AV}-XO+=q4E|qB%qVGv@Gi}^kbudwu(epPflM$$XH)6(~dL5 zKg?pW<0&a)ZNStNdXjYPNYH!;?G_ht_Jwi%0Nzd{F*{sW3c(uMUXv2${BcBrOZrPy zkuI!QhVYBzzsElXqsyo@eiNIjiaHlkm=Q(LjP3T&$Pj}~7>hpS6;>V-o3aFxQhg-` z2k>;_?X~#$mON~QMl3`+laIYCrguGJXy#~!iFfToIReBanCm~Nac?Nvi+mH6s zyd;;HV`Fzf^RM?IbVPz=`<-Pdq~&;5Z_jx zOy`{U%`~pFoj#s+wL97;)l0*+MruRX_#+%otV8=UXI7Tvwnoyct)A)xMJ!lFDU0YC-9O9J@{rmT?BS2;ZVfIs)6%LL85+mt8D3 z4l(lId@Gy@>y9-fp7VMD!Xl5*8+%qhwBn`u=iE-93!R?T8 zaB}~%ce^d!NcqT(d~>!Q6fnTL2rkq7y5EUs$+hEOeyrt2QfVc-%kEK$M0`=*7 zy>sdKYzr5BYpPGU0w~P?l;ywTBro7i^Ai7`N z>%+7gN;M7l=%3-nOQH!AXYS%@dQhvRrh`mP+Ec3|B^5E$({PO~v*t2#9acmC?AYK- zHAc@dhWI@4XGgI+6ciTSh5>gW3d|{H)VUnspEb$ z=o{ioq8C{|BYH7=B|-z})rT~^**}9{O{eB6E*=OSOn$!n{92Fm+ZPjTu>qeEkvGP2 zBODgU)={Zat3{5M%tNJ_oM#n&`QN2kcvknvL5Yn$=j2}%1DDF4SBezv-!mdZvI^2{ zpz?@y)_@hn>R~_zBXLHm-AbC1No8&VN;t1vzZSE0U`}4tP|2Y~)kkd_ykiwMq3D7= zTdHSAVa_~(E{PIoPfO3Rr(H3zrUpu6d7~oDepD1t?Z4+q59F>370lryH7ld`zL9}z zv0R(;3dB%@)=Y7$EMT=tfb5<$Y%TphOGmMPXl>E!n@#XG~}%WFs40;7F|D3N(i7-cy%~vKCRZFii8n z8B;iFTj_?3{4ohl8q;#t-LP1UuHa8C6`#PCUr7}aw7+;7BvE1P4XIRR?Plsr8E9b5 z&qABKjocL!|J)2(O0;LqIc=W;o2^i!df3;J+>;7;II|`G#ChG23}FgL zs_+{y3KM$Qr-H03(kx0LvEt`2Qv+hU5#Q$+EG_Y5{&bR1OVGn`ed$P@qvaca8O7CJC2l_c|4wc+WHu&) zpdSk*Mf#2aUzDO~-Wl@qSy1Bv_@X8o8RUW+YVZjx@u;J%4L=HkhQHeiQ z{wDp;YHkqrXi5*%9z3^rjczOdQQ=o_kz|-7^Cb#e_!R2|DS{^6(g|H7|U*{eHWBii1 zhLrEXHtH!hJQmv=X^eFshD;Co!p; zn&xMBOHmgbrYS^ondu3h#=LFJFnI=daaC*D;7YZgiezz+9Cw&`j{PT8COV9rv zF5St-5hSIv6Py={r`1oR;84b-o=0e%n?9rb?(6rNPVDP@&v#9#RnR##pL02iZ%*#Z z?9?#paINNh0IM?tS*Ys1?m83kS5|e;OM6i}OB-ZPgdB{oBThkym-rSPLv5y}Gn&bz zV$atAx4LI+Oy;fGFBx8;k>63G+0}gZ*{;Rpy)T!u7J4V(^M*Hptvq%PuJg~K0pLI- z8NmRpfdm#trTVM4MFtYeJgyN5I4GngXy#oK^G4_}S-T2=cP!tOlB=ErVLou+126U` zao~T*13$^riLn#u+lrj<*l_L!qKqkxT@5xP#o*8E@Uu^2*c}Q?cW;X zasTpOt*a@?Xl0O1z)uGL^H2)IGc-+eYJPzx~ zuI|Du`HRTdZ^25_0=s=Pvcp8{?=BU|;J)gbc+LLAHc4iTBJB}Vjn!kbzpN9PSQztLRf zxf2`G1E21>kr9_&nGM!*4qCP0Lre5Q;B_etr58qXLMzP`3FBTFtoDGhi@=ggeuBRt-!pz zeuc&f=E17A_-KF4%x!;ieX8JLrev>;-7V7>#|xLmcsN7ePUfw#fn0tGc=)u2YFJYZ zLhcq9M|InopIMKnUN54Oe^|i6^)_(mn;sTi*{DBM<7887ni=<`!P|h{YNZ9M*da3g zqy@_u#M^i;o)xJFMmx(T+Sd8kUEr_}sw?l%zLI`*q?qL?7_;_N=vZaK@T_S z_MYB&|7SuoUfqik1L>{ks-$ zQr#PTk6`_rU!BKXapUv4^G*Jbc!;k!9{8!Y;HTO$bKX2Ciov1n(wyM!eYnBHvVm~|uIfm)Bf_}*knBCx8gHf}7-EE_IH*{!!)BLlL#kdxI8tU+#Mlp(fZTx@syl^FUj*gjBs#v|W{-bw zQYI%V#~#ecFx}e9Ouw?2WI|(YB}3C)u>$(pN{A!N6{IuoU!g53V}*KJzRaEuF{oRn z!AhETrAp2jNNNH9*qdidu&ErZSdc2ReYX9Vp4e$Rqq| znJ|%IO}6~Tf3TET0~b#@ci=sujbMJX=TmlgigBWuw;HMLt3+h_-^GFDcO$zSeGK!@ zdQX|sb$=MdV{A9$Abj;lJ~MvfDSP>kNU`4Y*nPT_l^|oxbkp_s__3JqWzC8QD^_dX z?YO@xTF$!IDN~y64?D-5>!P+vyj!SiDZQ!asuXze>Ik2z5#oN|iJOs$w;%-EGq0gF z#89p63X9rQ1X_ZbJ@D6L0*OyI-C7NKD_s_2Q|aAF5X^P3&*lamirsZQfIg2Hc_!$M z>h9aIUT^*q!%@)<55+?3$*z6W29B%M2EI;d2Xn&9@KNlOcRxY;uQdAi~%v8A? z8FzL4U4TVR!zSx#xzu|EP(R&+p+|uNKtaR6!azUWul#)r6Y4F1gyo&$5sHC>Uk7t^ zW~J~kvBKK8zWwi8m`~I~B)LYfIxmR1?->-s#>N@9(cd>-WoX-w8;1&0$$*-su^_UZh5hP!nF}74 zq4Y7h%9^o^sZ!fzAFORheXk^jHhF!J4Cc*j84`YLab#?$m9C6D&o=xhj=e1 z_h`zA0Mo#nBbrZr zy2a3Mg6GTeEr#cQhj(=&LSGbK;6ek-b~_u>k8YQ!F{HYpPjVn*YE!zIS42p=xrBd@f4dBgf@AvqY4Ec@xJXK2nakLf z!4vdFz>MR^gann0&TNX3u{01Swl0`Umj)pwv}fj2NgHCjxXUt|0#c1f%c)O=qKfU; z35;H`pZ4ZmQV@Q8)iQ3}pTG#_0%P|Kr0Uai0^1aFf8lTn8=k<|>iDC#=BD$sjhMaM z_g^=|WYEQqEenCm*f@HcH{~A~GsB;J5m1j}5kf8}sWsMPCxp>*r*?Y${~iSY$%l}E z^e(LOKMRn}q%TbT@Oh2m6_$Pw?0;6Kt7$Ilh$H)-3k^fXqm02cEF*1j3j$evEc?n| z{4_SO3W>tN+RbM7B@`VmX|xAZm@`Uy!wy@vfF>W0?c~x`xL>0BQBC^X-(DWBwE5h@ zZ~AW=@}{S}PFAP6%JjIYZrnM$kQHFtX&}e1(wd|fMbO3u!^o1x-HAb4ayzhWmFWPM z@{knH-30iJ5sl-uQsE_PA#m1#b%8v{#_!J-s3^xd z9H31!6swTQ`iv(hDIF~W_2#!@J{LBipb+_+nOQ2eg|^e5eFIMN87j?u?wdl(MD1N0 zrX|>;m1B`%m)P%o!?-h1?x2)4pJq2#{sy!Y^@RNB3CCq?<< zdWQCd;dTBwJA9^9G`x9-nxI4sdKsMc2fy4}h|OB|_j5hb-{R!bcpX5*m5ihNe?XKr$W$JJ7Dt(XnFz``?lp&(PlQP zRL2M)@?9$3rHiuGH;(|h=XvOL9qR7PVOE*WSM&Q~v1+Zfba~^+qiGg8*GVnGw#me& zDXWY3Wsc#Q-hAhTX0!zS2pxOLM77l4l5sdV`gbmOVBW;IW{c8vy`5p5I*SbY{VdNF zG%2!jl(#!Z)#a;ljtboapTiW<4OY?myGnVb(E{{4rsF zS^FEZrOTt%+pyE=GmQ|Pmn8Rb(?bsAqFHHoFd4hUv_#!tp$wyT#wP(l?MBff5&U(w zJ2Wg3Frq~ZE*Yo5cCSgGl0Re4?L?cPWcmX2R;HT}&yN`n=-g3x3C~GLc)z23VVy;> z>*^!Gi_E9Wtj8X^ix!LbyN}g}>(ZZF_36p~6)fOIuC`*?m=IOe7cRhW3Fj@c#x)~m zy;M+ZkeriI=u4)fZVd)6qdHlHcHeBQOg?+qCpR;9KVZ4IcO{vL6 zSX6VO?wE<2Wp(jdGyX5qo3YizCZ*FWb^#^6iAO+U2v&WC=S)Oe!+^>s!K|aBglQDE3znp>NUec=9xnd+t4?9zvfng~?dZEC zR5KC{#mP!B8Sg}3*vu!WgF}``5c6has-8T|&{IZ#%Epz9X8~0cyIv0pI-(N7tJ4wc z4Wfjm%T|_+(1^XNlZeMnLwNAopf1D}=w#Dp43{#t*!9k2kC~L7JOp{FI zk^b3x*J`4)69%k9n{!K$_+fFtJJW$d91UJ-YsX^v!`dG1l!4gH`U}f>fJeYYAC&2( z&3q2dKzJhYnb;kXiYG zqE!G+6<#q;&o-#bs3}MSJcPWy5U@>-YKqSABNGtu$?Sy1rEft8`_9>e_xd^x4R5uN zCKGF5`Wq(SxNm?#`Wuj)8Mhd02CekVA79ltGb$JYh$(Vhuy-=zE(*vDUjYGM2HD^x zR14_cO2kbPJl~OFQmQCWgFL1>Ls}$~n_y>i5dxzi8e%+CD#1ul;I|%n7$Ep*a|yUk zkg*X$&DM9{6k#ASjeZw;J;9hfjJcy1wr>J0-+d+|;!*+69+z217TD;jHC$X{5#jf- zD8yl(1xi0_CpO+iIGY-vrpB>WWpM|^P+s<4CuUjGLW!R_##sC3FWNIhOCtl!TH@<& z09t8JL2X>rtJkE*;5d;EvyM9a>H8wl%cj#Ut%YppWyJY7%zKN$4D;c5JLv@$*tL%R z&AZCqlUvQIW=>O*r0$t}r9@0ST;;wxf0Q;~%4XrHecK5Mx3Ox+X?Q(^3+K}ver0#T zD{tiXdbq%8|1wHuppiL4^q$W!9l6kO=Iv~g%#>gW-f=it21-T#GBC~G~1@Etdq<}Blaj#!SB`^aUX7F?@C4ChPWM-5qMvZk-yRSuhA1nlE zhBMyz1fQ}v;-tYuDrkEsJ_tLpDA4QYihLL!p=^c6gq1?saxs!3&B1;NdB-{u4?|z) zR8T7b9%D3?9}G}zC(8>4@sf&+2hka+^<}kvK!PVTT`U@0ZklOZm65`=swSF--t=Ol zXn&Eb>#mvyV67*pmNm1`5q#rBr8-zqQMoVir9nq9OXIbGfaP?tS}Ca3a?~|*AFE>W zXxC8fAg|6FoX_GqpI5;h9r0eEn00WcsyWdE9Hb3Rj!F{LrcpjacOG_c_z!@Z_q88A z_5*>;Z-FmanGF3@D1X@&sRL2|cXWECKX_VrmdF^XwV6*3p_Xdk;KRtR;&0<-F zNW^IY(U(fP1;txq5pTr(8@4h2(=q-H9;d_GN5E0qhlv(yB{78{gu}a+wlfvoh7svv zPa>Wk?pG3}pXl;@BA&=k#{_l=5dgjkpK>RAs$AP>Vv%~(CwdKi^nYCXqV{{;j;p;e>0rOE0uM}gFN-hS7m>02p4w}ved zOec;M_furlWRgRWXQeHDqpdjf=F@idU}#pwE`d(jl}Srzgyzk58@o(!p_MdT%P**xm z>HFZVLPWJASJg497p<8;<(&q_skGT@`i-QF!gHK_tATKCkv1dyI{ES>lmrl8PejexOz~ zO28U4I~9A)+jIxN!nYFcok7~;PTJs=u-o>e<>P@+8N8$Y@>_1($nC)ptOfiQL@6x-it4xiph`|U&M@}rVUw$$$g}9{5Z9TY#(Y{LF0>L_7 zmREZ6GTm4lU75ps(y5UsP63N0>Wuulr0YJT!yyC4qio1aw2uIVcyMbt8Il!;Nw1;_ z+Gkoy?Pyg*Er?t3$3$mufol1!DVBJsH*hR_$I8c0g|Bh7A!jdl>ouUgv)9X6MIFIL zTBGUm|ElA(2=CK>XOJ3au%bj($YlANzZb>SnIsbb81O)St#AStgz48yLu}L!=o`zg zv$$LMgxF#CLko;PR65H3^h&8zJR>Hz5hcm&GLW7f&5_u|I(Iz(Vlfi2SMN^^Q@9J{ zq?>?x&1`Z5X||-uH)*0|WYI&>xeUU9)Is9;{Ld&Ma4GcPolGmQa2kDO6ywnWz5-8X ztP$1og#*n)#x@!CGhK;UuyQqMaHAv9Ni_|?;qR2LB#DLuIYa|$I5HU5IIln?S=G;#RX>%D8?k+0{q88zD*^3Pu{xepW`*}sa!bjG(u`mhN%m@1Li zcdsfR)VynH{i!xWo$EYXj43t;Gh;Ueq?qbLJgIP6=`nXzzQ{b~pu`=odce-u>xE6D z!#DbW+PL;`rrS5Z99s-IR3?Xw95QOPoQl1g%qc5g!N*5VsuLa1#qlrtq> zIn1)iDXB#n@;a46PU+yM5>o74b@j*lyZT(8>$#ujbKig5f85V~J9kgZgb}?DTZeN$uesZ;Zvj5=05B=Rj5DTa^CzwfC1#@G?xFf+FS}=FyR1os1 zXkKZr!w``wQrwljg1N)iB9XhG=^z>hez@!{MM@LyJ(qdMuTWyQwbma@H-Bd!CKuQB zrft;&y|-Luj`VS#mv>?#Y{&K{tv&%J@~h_z9XW1NH7Mwy8zep@L?dz!u~??qUGN%> zxUBO?#PF4VgG4aE+N9SAu9QCf`R<*9=VMr$Pw-s?e>lQ$s;Vgir;9ESf?x`d>>>1! z0eM+PE%snmOLT;{-`b53vTciJ-~)~Ry-h@YJVTVmfmDWf2dbc!3V9tw7A#+Di_E5K zJa)=gdoD`>yxe;e8{>z=>s@k|E;#3XkN=Uj6^9u{-pag4-pEWK8v~R4Z{ntVQl)%! zS#&zn#!Cui6%K%&cCWftEe~iQ>oh;DWqsjy-VpQLQTRJnsy+X`qtH`b951(!kreQI zCJe9m&wvSOwi4)243A~9^UyQr@My$XVt>NI(@Fj_TuIKtYE_dg_ZuJtt@qshB``V* z%8Z_q@YSiOR+UF^#)LOs(D-?~rUvQq(>>t((dxdgf-IiBVvlxYjx5`W!ej-&07^z8 zqC!18lAuWl3Sd^Ci>i&@UE2oU){I@n3PFKF5FH0^Tk-!eHFGG{s3x#9Ls?ZuRtO56 z-T9H@#3l{kY~-ktFRKdYo6>mtm;d1_I_@?vwm7lr^ka9t>IO5wy`O5H!p?DH2oeS+1Tw%rU5!H){ zz3IERY$cz4Wv5%&Hf0{Rib*E%dNA$k08$SFegeWA%qglyarV|?iE)8;tap0LnwDNT zG1W|mZFCnk6q558!O-2fs{df*$flu4YbfTL(+wpj=hAPgm-ygCeHL1D<0lRW z&8gaIgHnYc!mNB~Yv${ftfdG+ZGfq9j3p##eM}Ym&kzuOsa|Uilw8Ml?*wM7l zVW3C4+DjxV)G~L?R#3pOB(0!cOL*jigQ|i89$3r2x4lG4`L+8{@hHz7FEwDb&&`cu zcsBns}glb4L+Na;po>UvEF{iaE^!CONhjtNO<`0Vf^0=uEUTa>4zZ@!p_0e zRcvFCJ3bXt^$K67@nlkf6dADBj-YEb$M`>t8UkT#Jf&TD>&nY_?s!MN;nwBP35zvR zz3BmcsFZN$hm3u42cixP($7#)nc(6ai*l-xqWMR}t`g=WvA82FHj!5_emO5)I_J?M z9OIH`=DnpuUD+}fbGqYu6NARlY2F?xT~aS@A|e()jDPY8j*Gc;q}Nx`5|YDq(etwR z(`ihRnKN`=@8w>7U=j1`@M1!G=?Kg8yy{>~JNM+25QJTS<%K5bagC6b!ji zhMt@CRdMKC=GxZvHZL@>Rb32Upi}*$)prIpO9BnSvp26^HE|K>tJ*)w9d&+-Uor`_ z9U~iDd$?dX+Q~8lW5cFb+#AAqu=G6&PmB}Ttt0$VpvH+tH!9jQ9qUInj4ja{p~P%4 z9yvR`yCnYbQJ7J(LeYCsl*`jQzED>f&YbvX;R%RfoUSH%)q{^OEkhfCOJ4syhOFaR zr&~dtw_SZ_&$s@p-D1fO{bX_rL9RCoyj)qJwM&Ux49Wdu(UTv zkX0c|CZoW#W^HQ3xDx7YJ@4XV`QjyqgGsEYzGOik!>(5`^@^@p-$1njWaqgB4|e8= zZ7JKPB($sU%RPwX9G=abPdo}(M~J5s#fsm`S7-D!!d$gTXL>pF0i)pjDNN{n1IVkI zQ*vTKs*^MKr7USPm20L!l<+@Yk3IGow{9IGnX_j zOr6=VZl(hM5+MYA@wg9*uoi;q{o#6hmTd8He&BrX1u9|kArsy+P7Z1YJD0aX$}G^!+qV{6K91cg>w-+1pxz0gY0bJKixpboS+9a-8RqgG_z0P9DEL;nIY5$<#V delta 22146 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 diff --git a/docs/assets/MON_Server_Create_Alarm.jpg b/docs/assets/MON_Server_Create_Alarm.jpg index 5feeebca2a6f08efcc4b374ba94ff2187d31362f..a4b6b9d28af054146274084432fd9573755b7ab1 100644 GIT binary patch literal 20229 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 literal 21462 zcmd431zerGmIu0Vcc-+t7I$}dcXxMMphb$iyL)kWDaDJsyL)kp^EPeInRD*Uow+k_ z=KbDEcJj~4O0wdg_fG-`0fm5s0)vJD zM&kfuUg*zA000CG6ddAt0RRsM0sut@Lk4p0^8DPq{~`hafY;1{317JxTSfhi4Z_ra zIDavQKt8=4U(f%yD5&Eny%0;6Fz4wn2=$7K z;1>db?bc-A8+rc>fr8vlc?KoZ|Bhnl@y9gs96=3y*w?vQDIf0C02z+>#fd_P+!ttO=H za68qOu0D#AlqNZlbXQitWc_mcZ+&TWn1P=fkvKFk4`bNdF%|k|IwXOl367dA;wCtu zrTtg=9rvxS{SMVrsm2uN+S@yf_XVu#sN3!t1)MsQUw9ro+Y)&I6CS!6TE;)s6du%B z?LPp3__TigapV2M0y){dI%?X31S{u00suJ1$N2%Ex9<=?06_4%uD$`?S(!orfKhvX z04V&|1`o!&ylZ{Q0RTWo3K(sK|J}v_T%1wFr(Y2uXZ_cIbORWk(`1o1kS|QnWe9Xh zU+@bNrHnUt1EAtsR5kCwV3Ss}*MITx`zwyIrZ>Ry(?U z9(F{Pgk&v_dUx4Mo8^n}gw3?wRguYXxrk=l^#DV0A!5-Xm$X&PbXLa;MiL^3|4u$f9# zD>T1ZYddy$un^mMh9^VM%{C$5q_I?@$e;grKInuf8}SxW6bY&foaC{y1lY>Gk4Vq} z5M1?Wk;1na0CcJ>SW5FH^h^ul4<)$ma8SCzW=!2 z>eBqaPkr`fH2rQ6`l9f=H^?svZOvO1JI%OX5LM7gBk|ZgUIZrOi=UNV%uLSmg#KJ- z|FPY{P=>!$P4tD8`TA|v#ugtYNY=@^uiS5nY__d_VPt*D^!I=Xk|uBOI_7`j{7DS0 z%d1`Ae*k*&-rSxarcz&2FH%=8QfQgf31^i^68QrFg`o-g`YN`e`9;nRgC83P_vtEl z)zWGxFFVET^NUV70I%ia->O(m$3CHN~FU$!~Ao(p=VctjZ zLPWyEz+u6n(`2CBb1->BTbNdYvF_5VahO~;nWe(rUwv+LtJ%RrH28${W`zClUF-Cg z0g4p(N7ajuzF5&@4_J7-s+h3!L0MJW6=y>q(7IjNWTD>ZGnyG7`L8QrwTIqT{!}X! z&W7$x;$Hi7kzh#2<$(`9rDxM&iM>Sb3|4OOBgIpB<=rJ*{ab~}8i7=y6 zpv;CKuQlv+K0R7|$KM2c+LYN_^+GgJgT{>W@c+xe=S#$G1n=(C=d)@`EB&ko+Kgs9 z>>FFJ8Bew_tTbsm--a~!_Rgp`8y#O%ZRe9Z(qOqZzTJEIKLf@+UnQw6Z+z~JzJ3P4 zJp*!XZ5KbB<7t-Ds9~0bs`M0ZOgmUM{u`>(21Y4=^dHfCC^*ysV~?o>*gUM4$zedI4poXSDFW!)9eXU87FZ&j89%%NyjE&iEw4`id_K?1!Sc zR%wAKsV;hNc-6i@AYqvIhrn_{1X@US4XSuDcDo5@u2frla?PdS)fS>xdudl*15OK} zR9^#|-RhT&i0}e{d774s_16&#?cjzxol8NYK71ydX)1xic|PNo0i7%s1=H ze+I;ci)QwVyvn0HnaNluz~=~EYhsb=vz?L`5JS{qy^y>?xyqaTF^@&;?AkwXNFeIKWN)df^gvo5>UrFr%5XoSxc#| z8k>P=vTXDAvVJ?(3RUd0?VD>pTw7?4>w&1A{xzV#ySHz19P5E%{Wv({vW?EGv!KzG zQjMAZ1ymmI%$ol#_><2Dzi8)0K37@bY*>a}B1$zLQu_;#QKLZh9AHYo@YOqcft@d_1d4DWIo}g~MjS*!R8ehet?8!CjJ8j1dAAex8 zZ?6bh#T8q8pnD44P7nb{GuK?etoJX=w)zFim0JJA|1uysUwwsUeB^}xx2(#tE#_l1 zEeBf?oKvpt&PFbU+&yD;ho3lBg6!lbtma!wKhri~dr=RR_JSo0XoNs6byrGd3~PC3 zd?RO;xlA0OMU=#qm9OT-`7=S@TT;h@BQjlFswY*W4XJmlf#3S<&IR+eqx+hrzxD@n zKqM@Z8JE^N7bt~%gJo4y?=!9WrmZvN>4os63boN?I*yl97S=rjUwlb~{^8wH5Vb5` zBWr7H8}dqK-fWGVNH6NOSrnApnBAtLbbz^%hX05NiuNK|x2zZGJ~0g^&iJ^ZV=|#a zb(99Ua9DChuW%f%VU0Nq>Of#vH4zoHMyr4@x`p*R3aL=9o0vOc8=pjl=`#TDM40XK zKFiVSX8K;h~h|C_Rfr+Wxm;$7+xZ zWgem06EpC2gk}71i5sqxD<)po!{Clc)R%?UYH3l_ca=3t z*}_(?FDaM3Jv-FYtY9~tS;A<5u?f_YvaCm(c0_0ruM_}8>Xp1EYfHUdVp1#a2~;VD zvFz5I!ECFmu(4XyhQorK?#NlEMFrZmaeEtW$eCX;n&UI2BE>L@)LbgLwW}9g;|TkA zG9TD(c7J!ug_9xlE85X5yJ#XO5=)G)jNiB7>W#aFTV>UhOiZe6(Zfs)AN+;jOBYb8fz*1J0 zCD=aiZ0`1xA%psyS{<>CZZOU*r4(^HjW@bgb(6I$t9eimeO7WySL3T?c*4y<{o zI-u<4RS#W1M{--dBkAW<&(X8I^r|fN&kKEO8{K4golGL??}WRCmpfVMcLKLALz*lrOVkDM`cE{4Qs%hxLBP$-7cOl9D3egGH~l`X z_&!)qG12-k5m!VW?Ym}|3gJ?5-YXWN-VmB+z^)hY+K3W(7Z1D_hXme+1MN=&K?OxY zBV+(WCZJ~&AmW!7RM59K_<3OjynNyVc~~KP21JWRilKRZ%k9ezZl9_#DZAV|+uN{P zv05W3Qu~-Qs1R^1ND51AFRuSx>x@R}8!7x9KBb0Y3{IZ#igx z+pzi*Zz*h!YuZE`Yha4}cN~R=hl%DCceKKE;RA97&fqE89GAZaQu1f6N%|S3WB=}` z)HSsO>z&=TT6TQt>dAvAbE}a+JkS%$I76*oLoJqwG+1^#&=VA{F1aOzpk9TkUWLlt z_#)S>9Zl?bO`_d49E?RG^-FFm_*G&R(e}xJaA+dwVBkwD?b$yxudIp%ZjS9s`;$-- zO2CRM3dW#E<^3fP64!zvtbi`^4~|!7H8Bz6|I|M8+=jNxFj5u>7Hrv77Bx4<-xhmR zprIXHh~q2|sgsDeuoNxUR8$Q~ucvx{ zO#Ar6iWwF&%_RAb?yO2ia^XTU^PDxNnl_~dSI7&!NpWV#_WNd?X2eR!@~Vxe;X}`4 zIQIDe)Xv^rMiU7KqZ%iZ=_H!WJ8lnNlCf3D3?|YJRv*3e9x#riIZpyhS)1cVHX$n^3GMEnAROn*#U(3fd@ zvx09IwBhDx|KLd+yxre*_9&faM&@*vBBZYv-T&{ zvpta>A|6xTKBR^`V)N((J{&x`wQc%6qnS zMg9ZJ!FHtanBZlSId69TpMdwzfKC@CC6@o8)w=0Bi(HK>mQ=y3)OtO(8|WkVrd-F~ zZ}rME_s8~(I#+qlxfoiv74?YXmBlWF;;2CF_EhLYWtge7Lf4*Ht^@HbBUt) z>vs{BV?HnZ1hHuh58O8Lcg0{CYsY5*2XxR(<-bq)q|CL7Vf{o~u zb#OK5hVF~a`P*KW^OLs$j3%415uLQCOC{0OBLuDi3c#ltz_$SqP)N|wFWWcp@fj!> z02~FCITixAeKQdW7&tgZk0YZ4w{d1QmYu{&~ zDTPVJ7ILmhV+;(j(0|IAl!8T8p`oAZ6v(Ebrb=7h<{Ny{BpA$!xu%sdvmsDL^(9hS=d?o6xaw*OB zWIAjx>oO;yEMuZw9MP8SvXL3b30a=xfGQ1%x?Y8RE`rRsLw6b@O_XyN zBGT#D;mS7J(jOupuKerUDCM(#Y4g6}n)8vSb6+yVWA{gB_Lno+fXT3Y?&~#tXVKcu z*hNaJV;$WDn$l88CuPzUma*denR#ry?Xxzfsae_pq88OiOGT)*4D$d}%>^2>3Ay|j zbCRn30Ni0|`BQvj87n)u66M^XG6nT6h6zhxexD|xs<`ArB7tu&IC_~10&gC*Ad zgWUNuAR(fQ;=Jqo_+s@OQP$u-)U87XzhX7|L4(9IK>8Wrr7XumRAOQSioSA3_4XMs zY~b^xF9UL(ZKG*ll0v?tKwTudoKPDON7=L_f9ujcOH!fy_OY`~s3^`PbF93n#MUlb zRoLtHq1Jkst;t~9(%ugCE|++>EG<2QK{W=7?#{`j zqM6Phf94AdmpUuK9s!>w4KmUhPbV91{Tz*e?J*haTJLDx<-ZKM@4-)c=i_s7fmr&9 z0vKE4uMGY-4O)q8T+t&`-?{m5cwL&R)s;yJ#<-SQ+pbysnieU`s_KtfaekL~JEU=% z8k{3H+$-gmR?h&H+rYMMW8-Zye8D&!HydVU0Pd&HKXNcMBqFCT!lN^X@s{%rmMxzF z^d}qv$OlPUL6lNK%#^(BlU!_f{p4k3W-@Ia!>$_|fjUax>*pkwHHs8gd5)R--%jH& z-DbL$UkV>b&Rux8b)-$pddz+pI+wf>m3}f?d0Q_#{bK@oO;Qk#5}+>eV0gw9QP?WI zSxkq z91xtyM0U_&SZ7d~e1nGZ9{~E-@rq^PHf6^7Mm-&UINi#2lvFdZ8$7>eZ7YeJ-M*R` zL(k2Ru)mBwWE~e(c?uS_5CCoAD^k%i3Jov~)$q{-*y3#g&|Z^wmj_D|UwF-HRCX>j zmbU$snrmb<58GgsgulzgLy+Y8cEUrd=0n89&9df1$!4iYLR;8rT1a6K5K6*K3MfKG zQd6=nDZnXdC16@+Ykta=p>PpE{f_Zn@G`5Qh%>0X3ZeSon}dEKz{eTEcv60{9YS^X z;yr0T1nxmrzBEmDOOqhxMzKFEc*@%keK@7xQzoW;O>4_&EX&xkedb&YW>M#EF~SYA z4yJR9hzGqSTR0-{cnP6x`rQH&1mm*u!aJ2D3sWXivx_n17xN`xRBe6o zUW@5Q(ojOH+8AmvABH-KZe+jc^iFDiY&y8gXT4c%wp>K`N%7#;JY8$;QXiuqC4%Z z&BN~-Ib*mRE=y{XHXaP5%d_5kaCXeVW3*mOQYm6C)Z|&f*60X{IkJdae>tx$@bfdT zDG^D*r&gzJRT2ZO4WF)tSvm7|7C3a66)`PV8if9gENKDjX z2QeFiCplKEF_lj#rar#>T7IF7w$MWfOm2jd_%1tskfeE2TuFeI_FFbV`gdrlNg2qg z1!cc{L``t2`0@y7CG(_@aD*`5-xIhoKLZA;4A2nSs5F$UpsQhzDPk|25xAy&&m#h8 zu)shQK!fsK)IOf{ZqI6QDe>Cxg-(s8aS~lI?IH%XN#Azm{3BCT^04o2 z?Az{sPJNk@&VM5KZ>a;8=(yLd7eFk>b%$lxX$S@VRHN4)Nk=WY`SO~M#R4xAc?wUT zVs`7^;7@2@=XTvmWlXtxNjNP8>bc0}*H5VC&eEELJt@%fM%}^1!;0x}G|A6i{6#Jj zX`l9k!he`0tQ5a@uK9w30(sckyWaLIy`&FIg9PLA)28j4Wjb%v)BB}(W{(jfi}V8B zhNx61wFl&-EOc|q*1@Q8G&~!n+qF#hN|?(&I#6#dC@u{w!a6`t#crIK@Nsvz_2R19 zZKG2T8If&=b>Il^@~W{{Tu^eB$mr~mQhWC1U!6dNJ73hkZyg2h_Qs<-9vdx2qtWKf zKFx?ASjJ*?bTk+(vFr_ zLVCh3X15TJvG+Mfv1-M*cf=)p-{_7qW{La<&Bp0fECif~Kgn>`9tP+PxhzH$2V2vQ zgea$rlD-})yG?F3B~ASvXAn?5BB3f{ait-&zP4et!90zc%(L%ad#;!-t(6~A7_Ph) z%wp>F=)f54c`%$ZD>prj!zw7^Ch0j`#~Ke#3g*|jFn~i`ii&2=iH``@k=sVb!Q!4> zk;7T@;Pcdf>_#Oqvfgju?Mjs*s^say%t0mIPlA8-wwe2@s6ayz4k4Tv4hpAA87Tz! zyKc#W_GP|km-KDT*-;#fqHwfoHu@Tq2L%Pe_fAVEcpyDI+tRWYlEo;JPmN1Uf_laHReYihPZsN5$S<}X3phVfm(ShfzKgiDsg%a`(!(qagzBa zL@fu*vuH6Dv`bm8$(qIE&}Z+8B4l(6t@a{*b>atYzf-$wQIi>e+OhAE;3hEdlq_a7 zG!@fTn8W<}$l~BjV&|mZ8uXYuFn_li9fg-1{q~vEc#E25Jp++u!46gkZQt&iS;Ew2 z>b+`2h;Z$e@4Iasx6cJi=CG7dx*1^8E{wM*OcU)4-9!0MsyFl_8UxmB1f+{JHMIVV zsww;AgJ^D2WKzTwQX_u5`Jta+VPCB!$*1-6mCVD8<=m-CY@j5VrP;>RK%29+2+5$n z%`Kwii9yC-Nzty!8IxTX3hYrroe-Z$h&Db=zd-DlGTz$O&a^IzCtdT;Y3Z%38x;?R zSXgREM>O9=p`TiG`;5WZ0H{UumBX@1+L}HH_!4w5dJcC_{zJHrtU{UPQcTq=N^hR8 z`HvA)K`#SVNI_yB^d$`cqn;?z7rI=iRjhH}lhD16A3c})_ZxTg9%mldyf^dJVQtVai8_M+NsC3wP#sF~t|FYN!Voc>c?(0w^6vW3ohZzMkork}(=0~U)J z`R-XgzdlZub7iBB4vz9BQ~F`*7$CjESjQutMpI&98ZB4wgTyiE3+Cqr^H$2>%ErB) z%i~IypTUuEOnYbKK+0IPx%7FaxOYb(i!b~Rzle-Qie;BBhYocmqQaIjSIPT+x1VQ-A4H9Y?dHOVj>{ElGgXMr zX!Z`SH=7dP59B%b9>`SlowX}n<%xcmHL2RnQMs0&M@b(pJrF9QiS5RilS9ec!MfHb z4E~gg3#w~dyOU>O;C~t@eplL?j8*bLCBi#pJC`JO9@3@~E{DkRo|9O5(EQGHw4AQ` zCWno#wwyF*{Bzr7is*qs-dU;0wH~@?aKdbVs&3)bGayE1Bxs3&e)s(7u~;-1n4P5v zk3*FK9_d6y@wZ^Vc6w^lVa3UJR=EL{tK+XVo&>y%ufr$B)o=}gZ5En}EyyfYpP566 zi<)=Fo_*8zo?#!+xp%^7LVG_vuP?7@@|8rSxKjaZ4ff%Fcx^9Zt{p>&;n}aB5fB^M zFoYE@3>j4vu*SZL+Lg8;;~^bMT99^^N@rMZf5|JZ@T^SiESzz;WS^|c$p~IFSQP5K z+g3}^HFkdJKiL(Qh9+Uvj!-R<6`@9O7Vryuip=CRw=P)^;$oL+Iw_w4L-d^*j*c#m zaWy>S>ubnU0rLGP#!ZR!8lC9zr>cBvCqm1s zZ~7VUORzD9-HO`R&cndS!O%Neo(oN!5L;P%wMN2+rxg?wIr_{xR}yUQm;Z%D=sZHI zg_yTDez2`PgJCmxKRABKES7x(G}X1hS4>)F3#TZ4xIW?He3WZ>{tW-boiT6dFe1NO zw$Zz`RY@SXfH71mNqZ|7jkL*ZiG@lI-{x-%N`qYWTJ3y)ay}wx;Q)1_`}#Dyf6;&! zDnH(s{}8U(xhp(|>tV?(e(rghMH*9)1A!F`?&yz=PYRmG2N4KU#TjJUD7fPX;NBDnv~q4 z=$9?zydq5H6lHqao>f)%x>iiK?W}dvs27JKrs@(>mgQM4y$Vj3DLP*}V5EyXG4wx& zbDdG2>>WBG7#fWR$0RBRlg?CFokcqLk1 zp~p=cY%1R+G35sftrZ%t7&2|4N8LuA0friu9S}Ioe_Vr?(k4F(oEB4g7!=i&fYou# zMNMtFaI*HMmHModtWP=@;?}Ry<4KyAzGF&9S!!jU*Asp(iD%AGFTNQ%sOzkoe9^6k-Hr0W2wCJfOaQBw0sMuf zt96kp)X%L@CKe3Il^BWkb}u|`G?!!i6;7t8(|kC*bmrY5zMpwq65nZ_dH)5}z-k@- z`pK>8Y8@^q;LbL(lNELD;F`EO(QZUfSa!$D{E>>)I@h+-bHYmJR`p>xbj4ct;(wiK2uYRHZdVh8DUcaH`YMBs+tzjI ztZCD!clUoBwC7R&s&<>^8F-KP(O5d{p4vRvfLsbkzE4AwYV@)hf8XIGH9R(Afyqkwp2QJ9m+n3y@g^IYAt1s);DFqL#{4Gj-C9eV? znwItB21%JiXLi-&&`GK78T8X2GA4yKSw3Uax$Mm`b6$oe%11$4TFfBi_1L#GQTkbn zBbn|FO<&Uw+c!{k#MfKJHDt;M`&ha4d~#aG06xWJ6MCd&$8?4W2C<-bxV%kcsY-U3 zsUEEEmv3p`CD{%cW*37Tr|!ra2pkNXzj~BRR3S?AK}-0I9dlj%6g}KWeIW@V@KL*A zlz2rM)3s6IBmRnB8XquI9*QJ`bzdz_Z_>ir1rN;gLl~?&$v2NYFYsr(3fTPZR+Qh3uT@{W<-(xK3_HymLnx3{!_L^*9fO?LUTHpt#sw)$1r_KZGdFfOiq$6$Vw=xdGbADd2Ub!&+k;>LO-?lS+!fNMM^I`D2SIs}LdNX8ebO-gA zsP!%Rv~-aqJufZ0YirmueW|MlsjJ1q1O4~|s@Zw3HB1sTKBh^`TiHNr4gDXqR4sQyl(_3!($;_#H$q7H0owhF&qy) z#q+}M7*oSoSHngk+rb4S5eLUG)}2A)5_M*2b4^jR~AGM~FC?YZxlopQPvhc%*7ndwHq@n8>D)iGQJ!x3@SM~XV=LxJ$RBwAqXPsNk7Xbhyep*x8PKpt`TiD%Hwyi6K;z_@D5J0eC%M zf5hj%0--1zMb0r&LzqcX>FG33a{;5YfmeyZQQQaDqmJGe3lARru*A;kK8RCB)qDuM z4MiWEzAjHgZ^+&U>!ZG-X2_eZPSYINkz*DSid^@7U>nZKhu!6H&sS7LHt_zV8zvs?#N$_E|(%?E0tpv^(-e%(UgU9QQ%%D0u0Po|1(TQhG@(*THww zplshZs8d*gOPJRU(#?FqEq1jdU_uIVimK{4CZ?O34Twac0v<6i|%`Ud)2PnFN3zg;_O1Rv;IOYCZHu6i81ztbk%?x6|C??9?!h!{0mCg2sWhUZDVkC z<2wU19B?jCl%88t^00QdKrpzZew)x(#vw7LeJA12Fv#)LB^g3($myL|9&4p&p46rH zm-MdmRYjqn($|?_}mN&o~tUapNm{ z4< zW7bHEwhuCy3pSo({ZOADb`ts44D0BYnTfxHvD%}}<4w3f14e8-C(Yia&eksQ6s#Y= z9ULP+SE;4Jk)2__Q?X0BB6rkVz7u649}kG-YjKqbn+P9!Z4kDizZZ+4CWB8v*DyDX ztbi-6fZpq?2hh{$LXhY_>3xr?3Ri}DsJrQw%oX{gq#JLF7|J=Nl$dUT?OEa4=P zy>R~#vCq3d!cmxbe*qRimhH@zXW#cZp$|JkG68aq$_oa?%5vb&lOvs$jLwR){Q{_A zg?W?YwL+eGVz!5&@cu|3WqV8aDa~DHGQUk4;LPT3_;H2yF)f8ew&bpMxoX(($O&G=choqH<3}{BQk+14d15ljpX{Vpe?UqV!gDLxfx-8M`X7B-m?7n+Bg)LM6WP z@Md+NVf9PO^V7ZA{4&@04Cp9T0W|@414&tDdKVrE(v2~hx&5=c<4JjNMtNJR+C(2a zp)A4B@H%mwAXNv6dMa${z&%%p(g4cvR3*5qqigr8ydp97GO4V9 z8AtkOz-uV1>QZIg)?Du_=sSS695K0d4e4E^W^BC4yweWP5obOUdCTTi#Ej) z$G_qWtbPhE{1UK$hF@`i^}_irFfkAQ=F5xZZvmS})PsPZS^XC1+2Gt?_^ZILY=7pU z^*0?FjAJB7{;B2v9R>IY8S%d*iThc@UI`L!003C!H@|B^5+nDksJu*sapI-q90`(x z+o_sJu4ai%yFk23NuYqYQZL`7)bDlx3S9rJMYH%%uVL#&u@@bFfOY$LkCq{M>5Emch?(JnNf{vXmjL+M@i8w6;Rj$vehSR+ z9nADOv!(wj@JI4L1b!<1i&-tf2OJRp)cF0ARwqFHL-nYw0Yoy)(J$m4N4_X&sw3hP zYFO`n7hqk2%drJinQNQN?y>%{eM3g;x61!cBioAhx3EkvUGclppSCO|-dw+A^s`Qj zR#o-0N&>$Gmj99*IKH~02da-5Zk9mkeY0-NucHxxP5E~VJaa|YhVUG?W#Y2@3XY7OcHDbkpJip63C(&M z@^$YPx(StgNjEc2^b~_cNOVnIg{jE5e5#g^RTe(DTodW`w#r?*F&NECnRTUfBAB$> z*``fTba4=knt`=WXvoNBcQ|y%wS}A#J?>wkpoz~97Knx$f1`Dnw{6+UZhs@!3r94G zw~I?F5s1rVOSEzQ2rSV|iflyk;FQc zG5MFs@I%m%>n#p#Uu1O5k?UEf`&u*@PFXa1V)S=WtHaU|aY0z)D@L8jH>~j#<8V%~ zVp|NTHjb2}0nM%KV~&29%~g@^0((=c^)f^jkUkcVC_>AzGwUc;TsPIgM9jerNMMFW zUk%-lsr?$nV@sPW>wHO=zr|MLB5QIW|A5QsUnc>xN@GAdh=#W618VSFmD|jJKPmGL zpEwsZ_Jkkgx--=)8yhPVNt#IeX(c|!+>(aLDMSiTC-&3D=>23$g@%T5#*KD26OYMo zzhiLHfeUh!-15Oenhy|K>v$W3FxU*I=|6Y2mH-qC<$3v36b=Z2?b=D_&dy)zYa)yE z{*J&Z@$Pj6^mvSDw=pt@aEL5&6p5lBUMyoEr_?7!1^ymdP?E_YPwhmbz7zw^tzaW9 z4rVe}-|M{?8TlX@X?0)R22;AP(e>)bWOKrkj1Nt~c4jWbo(PEXqwkj|lQ?2Vdx+So zM($)$0DgjzAH7eEtCvVR*PAl_;A}%&mv_#3MBivpL;CHu`4~b30s_K>l$6xEw6ruY zFRwH!E2}WKVo55R?5L4Hu`)*eWpDd)rh@|~`tQ#o{yx*~KV^5E>i?YSFUPBqZ>B|2 zp#201k%NSZ{%asA7gqfNZOBj>I~Ho+`0_Ketlw_0dK_V{0}N$&XSC3)DZ24JZdyjJ z1!;oYxw}#&YzS^T%*2>+x;_UD45;^3z*f8zP1<_MV9>y)#S2GwwR_J%#?nBWB%QQK z;vhzsvF=;E#XweYWs(}Y)l~9)0giCd*zsVJY}^`f%B0yGDM1}n{lKVz*zr&l7;3Ck z@?H%tLYl;XjUtj}Hzn@=;jbf*%suugLSX+!;JAe0tbxbZbYkST3zB+*WLYV$xa6SX ziDRN*!t0l@anVVHd9Kz%7Nk*Kf}&!V#2_?9*;0fIphBYJ6ESdxB#@yzjPLfrv3Z10zexMuucnB3`nF~wGBC}HKhlv*QLI|=%7Nb*SKotX(LlBD&*8l@Yp;eEj zkRIejCZ6g4seqyDKQ2++Y^y%w=CztMn4uy$e}L@ziDv*dRq-D*TVXibt$&Z{Nenet zvzb=gk83EL^P$>0PLa|&{7v#9I*d^{!4Wj zUhq3YIKzG#PIIm>?oXwiA}LS(pACt4{0>|fdwh>H&gv~HH573%1yPx!0>aHW_CKI{Uky13%>MC2rMjTH&W%I*_ip9bwdZQn=vsq#^H80w`_HnXEXF8weL=q$_BF8V{qAchLL&unm{NG=6FW zvtdH@_qiZ*J_^e;8c7nomg%*~9?;bWW}E^SCHM_^F4Y93(tOgP(CU)Px69$E%9^kV zRM<~?2b_d-yW^UW`AQFQpZU6A20XkwCz^LJ5_CyyaRRuMHC8sZ*4AO>OlgKHSklnZ zQq$7XQXev-tl3pl;;`DXu6Xjjd^_>-;2Z?_?<0SIa4w)=aC-JBI=f>W`2B=K6+gkR z$qoD#oDVr3a%de>6ULC2FG#<`7xLwt`9Jr#NTkCoHKqC^yiR8lY~y<+W>+RF+CJ-j zko|Iq|zyu&C@-qTI&W}1p?E+%SuSlBea8{6|xkWgmjIkNW zeM46H-koH^4nmt=nniNVo+M1;&K)%SSu$K-bJrzt z+c>TXd2HFi&#qZQY824$p*w~gm@;K-h-0|cLlBm-iYl7uhb?HTWH-7Z&>&XI%`{1+ zAP5}p2A_Jc!I@&&TyWG)VkMLG)4fWLp7QasOXuMl{1+ewMkCh{WnrHI3RF4l!V6#w zxM|0ZtlwuS&EUnDZL?*E^Gjcs*pnic;=(vDwTAXFf}^8TFC2L0zfW?adn`yuFzCor z6QOaIt|O~p4HqRLh{C1BYVJ+rAlKAch4l$NMRj}+3%mi&udnbHUGF2*ltFhiWH5)o zP)3GRgFIR^SYw&Kjfy#CI3@J(nZbkJ@I)bsV;AlbJA$dJ#5FL-De1WE<&>e2hxFD; zLoNIYsxv9xy6GlQh0YFxb}iHuvSKgVq$B(`Q5wV$7W67>{dO}p;?3^PWI(mLMq{e% z;%R!rI+tDNyH&sAc9=y^wE72fo16bLHgQTT05lZ`poebr1N7?xrj^y6;lbg<(JU8= z=Uzf&RZ87J>h~ww4&gqQ{F$_$J}09bvdx7HeAp`5cSqzJ7tv0o)Ye_ zU0m%QAmC8a&5(*Tbkrf+gEhUCfg1MsRc10G!G<)(aXH^X`6W-W+!UcRC`-}lkErSE zXs4RGYehxCYnPSL32I=+!<~aoH25{7EMc{nhSv&UR7%D41is8@e?z7ziOEh0W2XwA zzJoIlwLQhnrigzvCC1L>d%LXXa8-pK0`2tI1h_OT-!|q(YYea+ zXh>y$DHfX7t1Wr2EP}M^tRNEiWy?+DM&zrfi4EYLzRHtsFy!nCc<{{?U#fe=f@w3?Wb|G|GIpI zMubJ~TIeD{i!zmZHa`*!x#O7l=;7o@VMz8#8xkxfhOuJiv}FP%Q*k0(#RYm0VhUKT zG#6y>ec`;%A8b$(rNB~xSV8>XS~m3Obsbj z{qb1U9R<@5z7~|~5w2NhIbEV6Hk_~KNX$Lz0E(gDX>QTXZ>y9Z&scSn#+7`X16(-zltS=(T>AFwzZe+H7F+(ZubE3H z6#u%hKj}g9-)e*uRui7~@o|+skNAu68A3b|ET+MLPPG~8769e1IEw)|^r=&e!-m%vxYPEx1 z3Cf!oU_oGGh96Ohj`UsENzPb?8S`hY)zxDrssy2gFjvc=fn(s7x}cksV&0YtNKt&L z1N(s5{Hb!Jw5qzKagDN_8V0c^oz8AEoSw%rYmce9b%^*D2eWBLi#9=nIK374u$LVT z78YTPxF*j#9%Lg~e(xx5&p@)acJ(;rrFr!G%FtdnFXDxmsbh@Ab1OrP)ge;nyp~R1 zkjfPzfo?z>&@A_Rz19ml{<@yLUNoU64K7dw6oWRta$s&LvTS#=g8&pI6_AzUE{&3P z9;E6_sTRerYRo^cp2Kaf=CaqjmxH>43DMWo^wVMQXn}-sl^h9ixEaq z&vA^|tbX`9>N|$ziavUP`k6X}(53ecOJ4O?oyvMuxkjss(EFG~~MzXdMv00S2F%cL_VR@cM(zr{D$MpiRWLpJV5z?c+))@(ny zpYZipuMV8^bvMFK@%MdADT48w8pF1JFDz-}zTJVgVI5J4j?Moy9eG6A9_wL*r4xQi z^Z|v%q>%g?u2*qwHzcr-Y$uhO+j1pZTh+0dQ>~2DRa%#L8q3M`>*dB}Xa^_6npjL< zMORNkKwWz#HiY$l1B>cN?A|d3JG6JE7<(e$SD_#xp|G#k`Ls~bE{bfVMSc552We!B zD>E*%GmG!HKP=m<8qex1KLeY6Vf*K*V7!v>^VxfCINHDXPZ`6F-%T6F&r|}~Fh2n}sCI_5qeZ|6@ zk5UZp_SKL7Cn^Kg{30cG+!&&3_yMn?9Wb5*t3lvrkvcm?Pvq4ddIqZQ{?IUE`%JgwaSxN+LROf}N7ASO*jmIT720%4@sbL$Or6 ziVy{<(K~BlTTkS9B-yHAX#*WI3;=!D9e;=XI}KZBy1ZdaDea~x3ZQ_xEv!cZw^grQ z!_l0u__~{3)G{tj?X9Y_^-|ffvqH_0ydXl9mx()Q?lij{)QM=UjI{bD)mj%L7&l~t zq$%}MXDPKS0ijF3l!ol&V{UU^LNr@~SgU}Tf;{RoL>6qbCV^h??TAYaCe-JELM*4% zbR1L|!I58i1F!J^0Ec2p^SWXUrba^G*l^db2q{>0h7Lnd1%z>7bkfF&`%^peO7X(? zxzMqM<*N(l33n9A333?`tBC) zOzx9twuPeF3x;F-oFxR+(@A*7pas=KRl4QfjhYt8A`>gLW@ga|s%n&4D@K0w4!^_o zZ;R+w11hKi8F8YeH7ruk!+-*Zpcb_p11qF!+SmjFKk#_u6CG()j|ejRiRYmLl4(QW_Y3gO_F(sr9ESrLxrykC#>o{^rR}K+-rK5(m9-9dIo(bpqPm2qk;W5&|{D# zU5N8#vxzOo`I%>l*B|C(ok88l^-I(5%aao=NWo zL74ca74oH--^gVSe6u&?;lO>F{{ST~(3N(f@jj852RJ{;&sTF0%i;&pgXs)0oI-fg ueLj`qM$HEX>D|AAk9VX-4Y>z_S?Iy}CFE5>R|@41U53EA*>`hakN?@`C8f3i diff --git a/osm_mon/cmd/mon_collector.py b/osm_mon/cmd/mon_collector.py index 94c3883..3e493de 100644 --- a/osm_mon/cmd/mon_collector.py +++ b/osm_mon/cmd/mon_collector.py @@ -27,11 +27,12 @@ import sys from osm_mon.collector.collector import Collector from osm_mon.core.config import Config +from osm_mon.core.database import DatabaseManager def main(): - parser = argparse.ArgumentParser(prog='osm-mon-collector') - parser.add_argument('--config-file', nargs='?', help='MON configuration file') + parser = argparse.ArgumentParser(prog='osm-policy-agent') + parser.add_argument('--config-file', nargs='?', help='POL configuration file') args = parser.parse_args() cfg = Config(args.config_file) @@ -47,6 +48,9 @@ def main(): log.info("Starting MON Collector...") log.debug("Config: %s", cfg.conf) log.info("Initializing database...") + db_manager = DatabaseManager(cfg) + db_manager.create_tables() + log.info("Database initialized correctly.") collector = Collector(cfg) collector.collect_forever() diff --git a/osm_mon/cmd/mon_evaluator.py b/osm_mon/cmd/mon_evaluator.py index ba9a420..3835d7e 100644 --- a/osm_mon/cmd/mon_evaluator.py +++ b/osm_mon/cmd/mon_evaluator.py @@ -26,12 +26,13 @@ import logging import sys from osm_mon.core.config import Config +from osm_mon.core.database import DatabaseManager from osm_mon.evaluator.evaluator import Evaluator def main(): - parser = argparse.ArgumentParser(prog='osm-mon-evaluator') - parser.add_argument('--config-file', nargs='?', help='MON configuration file') + parser = argparse.ArgumentParser(prog='osm-policy-agent') + parser.add_argument('--config-file', nargs='?', help='POL configuration file') args = parser.parse_args() cfg = Config(args.config_file) @@ -47,6 +48,9 @@ def main(): log.info("Starting MON Evaluator...") log.debug("Config: %s", cfg.conf) log.info("Initializing database...") + db_manager = DatabaseManager(cfg) + db_manager.create_tables() + log.info("Database initialized correctly.") evaluator = Evaluator(cfg) evaluator.evaluate_forever() diff --git a/osm_mon/cmd/mon_server.py b/osm_mon/cmd/mon_server.py index e05f4b8..6698339 100644 --- a/osm_mon/cmd/mon_server.py +++ b/osm_mon/cmd/mon_server.py @@ -27,12 +27,13 @@ import logging import sys from osm_mon.core.config import Config +from osm_mon.core.database import DatabaseManager from osm_mon.server.server import Server def main(): - parser = argparse.ArgumentParser(prog='osm-mon-server') - parser.add_argument('--config-file', nargs='?', help='MON configuration file') + parser = argparse.ArgumentParser(prog='osm-policy-agent') + parser.add_argument('--config-file', nargs='?', help='POL configuration file') args = parser.parse_args() cfg = Config(args.config_file) @@ -48,6 +49,9 @@ def main(): log.info("Starting MON Server...") log.debug("Config: %s", cfg.conf) log.info("Initializing database...") + db_manager = DatabaseManager(cfg) + db_manager.create_tables() + log.info("Database initialized correctly.") loop = asyncio.get_event_loop() server = Server(cfg, loop) server.run() diff --git a/osm_mon/core/common_db.py b/osm_mon/core/common_db.py index f15ae97..8f2f552 100644 --- a/osm_mon/core/common_db.py +++ b/osm_mon/core/common_db.py @@ -21,12 +21,9 @@ # For those usages not covered by the Apache License, Version 2.0 please # contact: bdiaz@whitestack.com or glavado@whitestack.com ## -from typing import List - from osm_common import dbmongo, dbmemory from osm_mon.core.config import Config -from osm_mon.core.models import Alarm class CommonDbClient: @@ -135,16 +132,3 @@ class CommonDbClient: def get_project(self, project_id: str): return self.common_db.get_one('projects', {'_id': project_id}) - - def create_alarm(self, alarm: Alarm): - return self.common_db.create('alarms', alarm.to_dict()) - - def delete_alarm(self, alarm_uuid: str): - return self.common_db.del_one('alarms', {'uuid': alarm_uuid}) - - def get_alarms(self) -> List[Alarm]: - alarms = [] - alarm_dicts = self.common_db.get_list('alarms') - for alarm_dict in alarm_dicts: - alarms.append(Alarm.from_dict(alarm_dict)) - return alarms diff --git a/osm_mon/core/database.py b/osm_mon/core/database.py new file mode 100644 index 0000000..61bd180 --- /dev/null +++ b/osm_mon/core/database.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- + +# Copyright 2018 Whitestack, LLC +# ************************************************************* + +# This file is part of OSM Monitoring module +# All Rights Reserved to Whitestack, LLC + +# 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. + +# For those usages not covered by the Apache License, Version 2.0 please +# contact: bdiaz@whitestack.com or glavado@whitestack.com +## + +import logging +import os +from typing import Iterable + +from peewee import CharField, FloatField, Model, AutoField, Proxy, ForeignKeyField +from peewee_migrate import Router +from playhouse.db_url import connect + +from osm_mon import migrations +from osm_mon.core.config import Config + +log = logging.getLogger(__name__) + +db = Proxy() + + +class BaseModel(Model): + id = AutoField(primary_key=True) + + class Meta: + database = db + + +class Alarm(BaseModel): + uuid = CharField(unique=True) + name = CharField() + severity = CharField() + threshold = FloatField() + operation = CharField() + statistic = CharField() + metric = CharField() + + +class AlarmTag(BaseModel): + name = CharField() + value = CharField() + alarm = ForeignKeyField(Alarm, related_name='tags', on_delete='CASCADE') + + +class DatabaseManager: + def __init__(self, config: Config): + db.initialize(connect(config.get('sql', 'database_uri'))) + + def create_tables(self) -> None: + db.connect() + with db.atomic(): + router = Router(db, os.path.dirname(migrations.__file__)) + router.run() + db.close() + + +class AlarmTagRepository: + @staticmethod + def create(**query) -> Alarm: + return AlarmTag.create(**query) + + +class AlarmRepository: + @staticmethod + def create(**query) -> Alarm: + return Alarm.create(**query) + + @staticmethod + def get(*expressions) -> Alarm: + return Alarm.select().where(*expressions).get() + + @staticmethod + def list(*expressions) -> Iterable[Alarm]: + if expressions == (): + return Alarm.select() + else: + return Alarm.select().where(*expressions) diff --git a/osm_mon/core/models.py b/osm_mon/core/models.py deleted file mode 100644 index 1810c9b..0000000 --- a/osm_mon/core/models.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2018 Whitestack, LLC -# ************************************************************* - -# This file is part of OSM Monitoring module -# All Rights Reserved to Whitestack, LLC - -# 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. -# For those usages not covered by the Apache License, Version 2.0 please -# contact: bdiaz@whitestack.com or glavado@whitestack.com -## -import uuid - - -class Alarm: - - def __init__(self, name: str = None, severity: str = None, threshold: float = None, operation: str = None, - statistic: str = None, metric: str = None, tags: dict = {}): - self.uuid = str(uuid.uuid4()) - self.name = name - self.severity = severity - self.threshold = threshold - self.operation = operation - self.statistic = statistic - self.metric = metric - self.tags = tags - - def to_dict(self) -> dict: - alarm = { - 'uuid': self.uuid, - 'name': self.name, - 'severity': self.severity, - 'threshold': self.threshold, - 'statistic': self.statistic, - 'metric': self.metric, - 'tags': self.tags - } - return alarm - - @staticmethod - def from_dict(data: dict): - alarm = Alarm() - alarm.uuid = data.get('uuid', str(uuid.uuid4())) - alarm.name = data.get('name') - alarm.severity = data.get('severity') - alarm.threshold = data.get('threshold') - alarm.statistic = data.get('statistic') - alarm.metric = data.get('metric') - alarm.tags = data.get('tags') - return alarm diff --git a/osm_mon/evaluator/evaluator.py b/osm_mon/evaluator/evaluator.py index cc9a8ad..2f22625 100644 --- a/osm_mon/evaluator/evaluator.py +++ b/osm_mon/evaluator/evaluator.py @@ -28,8 +28,8 @@ import time import peewee from osm_mon.core.config import Config +from osm_mon.core.database import Alarm from osm_mon.core.message_bus_client import MessageBusClient -from osm_mon.core.models import Alarm from osm_mon.core.response import ResponseBuilder from osm_mon.evaluator.service import EvaluatorService, AlarmStatus diff --git a/osm_mon/evaluator/service.py b/osm_mon/evaluator/service.py index b3b0d26..de3798b 100644 --- a/osm_mon/evaluator/service.py +++ b/osm_mon/evaluator/service.py @@ -25,9 +25,10 @@ import multiprocessing from enum import Enum from typing import Tuple, List +from osm_mon.core import database from osm_mon.core.common_db import CommonDbClient from osm_mon.core.config import Config -from osm_mon.core.models import Alarm +from osm_mon.core.database import Alarm, AlarmRepository from osm_mon.evaluator.backends.prometheus import PrometheusBackend log = logging.getLogger(__name__) @@ -56,11 +57,11 @@ class EvaluatorService: return BACKENDS[self.conf.get('evaluator', 'backend')](self.conf).get_metric_value(metric_name, tags) def _evaluate_metric(self, - alarm: Alarm): + alarm: Alarm, tags: dict): log.debug("_evaluate_metric") - metric_value = self._get_metric_value(alarm.metric, alarm.tags) + metric_value = self._get_metric_value(alarm.metric, tags) if metric_value is None: - log.warning("No metric result for alarm %s", alarm.uuid) + log.warning("No metric result for alarm %s", alarm.id) self.queue.put((alarm, AlarmStatus.INSUFFICIENT)) else: if alarm.operation.upper() == 'GT': @@ -77,15 +78,25 @@ class EvaluatorService: def evaluate_alarms(self) -> List[Tuple[Alarm, AlarmStatus]]: log.debug('evaluate_alarms') processes = [] - for alarm in self.common_db.get_alarms(): - p = multiprocessing.Process(target=self._evaluate_metric, - args=(alarm,)) - processes.append(p) - p.start() - - for process in processes: - process.join(timeout=10) - alarms_tuples = [] - while not self.queue.empty(): - alarms_tuples.append(self.queue.get()) - return alarms_tuples + database.db.connect() + try: + with database.db.atomic(): + for alarm in AlarmRepository.list(): + # Tags need to be passed inside a dict to avoid database locking issues related to process forking + tags = {} + for tag in alarm.tags: + tags[tag.name] = tag.value + p = multiprocessing.Process(target=self._evaluate_metric, + args=(alarm, tags)) + processes.append(p) + p.start() + + for process in processes: + process.join(timeout=10) + alarms_tuples = [] + log.info("Appending alarms to queue") + while not self.queue.empty(): + alarms_tuples.append(self.queue.get()) + return alarms_tuples + finally: + database.db.close() diff --git a/osm_mon/migrations/002_add_alarm_tags.py b/osm_mon/migrations/002_add_alarm_tags.py new file mode 100644 index 0000000..22f5de8 --- /dev/null +++ b/osm_mon/migrations/002_add_alarm_tags.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- + +# Copyright 2018 Whitestack, LLC +# ************************************************************* + +# This file is part of OSM Monitoring module +# All Rights Reserved to Whitestack, LLC + +# 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. + +# For those usages not covered by the Apache License, Version 2.0 please +# contact: bdiaz@whitestack.com or glavado@whitestack.com +## +"""Peewee migrations -- 002_add_alarm_tags.py. + +Some examples (model - class or model name):: + + > Model = migrator.orm['model_name'] # Return model in current state by name + + > migrator.sql(sql) # Run custom SQL + > migrator.python(func, *args, **kwargs) # Run python code + > migrator.create_model(Model) # Create a model (could be used as decorator) + > migrator.remove_model(model, cascade=True) # Remove a model + > migrator.add_fields(model, **fields) # Add fields to a model + > migrator.change_fields(model, **fields) # Change fields + > migrator.remove_fields(model, *field_names, cascade=True) + > migrator.rename_field(model, old_field_name, new_field_name) + > migrator.rename_table(model, new_table_name) + > migrator.add_index(model, *col_names, unique=False) + > migrator.drop_index(model, *col_names) + > migrator.add_not_null(model, *field_names) + > migrator.drop_not_null(model, *field_names) + > migrator.add_default(model, field_name, default) + +""" + +import peewee as pw + +SQL = pw.SQL + + +def migrate(migrator, database, fake=False, **kwargs): + """Write your migrations here.""" + + @migrator.create_model + class AlarmTag(pw.Model): + id = pw.AutoField() + name = pw.CharField(max_length=255) + value = pw.CharField(max_length=255) + alarm = pw.ForeignKeyField(backref='tags', column_name='alarm_id', field='id', + model=migrator.orm['alarm'], on_delete='CASCADE') + + class Meta: + table_name = "alarmtag" + + +def rollback(migrator, database, fake=False, **kwargs): + """Write your rollback migrations here.""" + + migrator.remove_model('alarmtag') diff --git a/osm_mon/migrations/003_rename_monitoring_param.py b/osm_mon/migrations/003_rename_monitoring_param.py new file mode 100644 index 0000000..2d5108f --- /dev/null +++ b/osm_mon/migrations/003_rename_monitoring_param.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- + +# Copyright 2018 Whitestack, LLC +# ************************************************************* + +# This file is part of OSM Monitoring module +# All Rights Reserved to Whitestack, LLC + +# 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. + +# For those usages not covered by the Apache License, Version 2.0 please +# contact: bdiaz@whitestack.com or glavado@whitestack.com +## +"""Peewee migrations -- 003_rename_monitoring_param.py. + +Some examples (model - class or model name):: + + > Model = migrator.orm['model_name'] # Return model in current state by name + + > migrator.sql(sql) # Run custom SQL + > migrator.python(func, *args, **kwargs) # Run python code + > migrator.create_model(Model) # Create a model (could be used as decorator) + > migrator.remove_model(model, cascade=True) # Remove a model + > migrator.add_fields(model, **fields) # Add fields to a model + > migrator.change_fields(model, **fields) # Change fields + > migrator.remove_fields(model, *field_names, cascade=True) + > migrator.rename_field(model, old_field_name, new_field_name) + > migrator.rename_table(model, new_table_name) + > migrator.add_index(model, *col_names, unique=False) + > migrator.drop_index(model, *col_names) + > migrator.add_not_null(model, *field_names) + > migrator.drop_not_null(model, *field_names) + > migrator.add_default(model, field_name, default) + +""" + +import peewee as pw + +SQL = pw.SQL + + +def migrate(migrator, database, fake=False, **kwargs): + """Write your migrations here.""" + + migrator.rename_field('alarm', 'monitoring_param', 'metric') + + +def rollback(migrator, database, fake=False, **kwargs): + """Write your rollback migrations here.""" + + migrator.rename_field('alarm', 'metric', 'monitoring_param') diff --git a/osm_mon/migrations/004_remove_alarm_fields.py b/osm_mon/migrations/004_remove_alarm_fields.py new file mode 100644 index 0000000..b9477ac --- /dev/null +++ b/osm_mon/migrations/004_remove_alarm_fields.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- + +# Copyright 2018 Whitestack, LLC +# ************************************************************* + +# This file is part of OSM Monitoring module +# All Rights Reserved to Whitestack, LLC + +# 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. + +# For those usages not covered by the Apache License, Version 2.0 please +# contact: bdiaz@whitestack.com or glavado@whitestack.com +## +"""Peewee migrations -- 004_remove_alarm_fields.py. + +Some examples (model - class or model name):: + + > Model = migrator.orm['model_name'] # Return model in current state by name + + > migrator.sql(sql) # Run custom SQL + > migrator.python(func, *args, **kwargs) # Run python code + > migrator.create_model(Model) # Create a model (could be used as decorator) + > migrator.remove_model(model, cascade=True) # Remove a model + > migrator.add_fields(model, **fields) # Add fields to a model + > migrator.change_fields(model, **fields) # Change fields + > migrator.remove_fields(model, *field_names, cascade=True) + > migrator.rename_field(model, old_field_name, new_field_name) + > migrator.rename_table(model, new_table_name) + > migrator.add_index(model, *col_names, unique=False) + > migrator.drop_index(model, *col_names) + > migrator.add_not_null(model, *field_names) + > migrator.drop_not_null(model, *field_names) + > migrator.add_default(model, field_name, default) + +""" + +import peewee as pw + +SQL = pw.SQL + + +def migrate(migrator, database, fake=False, **kwargs): + """Write your migrations here.""" + + migrator.remove_fields('alarm', 'vdur_name', 'vnf_member_index', 'nsr_id') + + +def rollback(migrator, database, fake=False, **kwargs): + """Write your rollback migrations here.""" + + migrator.add_fields('alarm', + vdur_name=pw.CharField(max_length=255), + vnf_member_index=pw.CharField(max_length=255), + nsr_id=pw.CharField(max_length=255)) diff --git a/osm_mon/migrations/__init__.py b/osm_mon/migrations/__init__.py new file mode 100644 index 0000000..d81308a --- /dev/null +++ b/osm_mon/migrations/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +# Copyright 2018 Whitestack, LLC +# ************************************************************* + +# This file is part of OSM Monitoring module +# All Rights Reserved to Whitestack, LLC + +# 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. + +# For those usages not covered by the Apache License, Version 2.0 please +# contact: bdiaz@whitestack.com or glavado@whitestack.com +## diff --git a/osm_mon/migrations/conf.py b/osm_mon/migrations/conf.py new file mode 100644 index 0000000..c6bda5a --- /dev/null +++ b/osm_mon/migrations/conf.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + +# Copyright 2018 Whitestack, LLC +# ************************************************************* + +# This file is part of OSM Monitoring module +# All Rights Reserved to Whitestack, LLC + +# 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. + +# For those usages not covered by the Apache License, Version 2.0 please +# contact: bdiaz@whitestack.com or glavado@whitestack.com +## +import os + +DATABASE = os.getenv('OSMMON_SQL_DATABASE_URI', 'sqlite://') diff --git a/osm_mon/server/service.py b/osm_mon/server/service.py index 60cb3ec..1d546e3 100755 --- a/osm_mon/server/service.py +++ b/osm_mon/server/service.py @@ -21,10 +21,12 @@ # contact: bdiaz@whitestack.com or glavado@whitestack.com ## import logging +import uuid +from osm_mon.core import database from osm_mon.core.common_db import CommonDbClient from osm_mon.core.config import Config -from osm_mon.core.models import Alarm +from osm_mon.core.database import AlarmRepository, Alarm, AlarmTagRepository log = logging.getLogger(__name__) @@ -36,16 +38,41 @@ class ServerService: def create_alarm(self, name: str, - threshold: float, + threshold: str, operation: str, severity: str, statistic: str, metric_name: str, tags: dict) -> Alarm: - alarm = Alarm(name, severity, threshold, operation, statistic, metric_name, tags) - self.common_db.create_alarm(alarm) - return alarm + database.db.connect() + try: + with database.db.atomic(): + alarm = AlarmRepository.create( + uuid=str(uuid.uuid4()), + name=name, + threshold=threshold, + operation=operation.lower(), + severity=severity.lower(), + statistic=statistic.lower(), + metric=metric_name + ) + for k, v in tags.items(): + AlarmTagRepository.create( + name=k, + value=v, + alarm=alarm + ) + return alarm + + finally: + database.db.close() def delete_alarm(self, alarm_uuid: str) -> None: - self.common_db.delete_alarm(alarm_uuid) + database.db.connect() + try: + with database.db.atomic(): + alarm = AlarmRepository.get(Alarm.uuid == alarm_uuid) + alarm.delete_instance() + finally: + database.db.close() diff --git a/osm_mon/tests/unit/core/test_common_db_client.py b/osm_mon/tests/unit/core/test_common_db_client.py index 7102226..e584149 100644 --- a/osm_mon/tests/unit/core/test_common_db_client.py +++ b/osm_mon/tests/unit/core/test_common_db_client.py @@ -27,7 +27,6 @@ from osm_common import dbmongo from osm_mon.core.common_db import CommonDbClient from osm_mon.core.config import Config -from osm_mon.core.models import Alarm class CommonDbClientTest(unittest.TestCase): @@ -147,37 +146,3 @@ class CommonDbClientTest(unittest.TestCase): decrypt_vim_password.assert_any_call('vim_password', schema_version, vim_id) self.assertRaises(AssertionError, decrypt_vim_password.assert_any_call, 'vrops_password', schema_version, vim_id) - - @mock.patch.object(dbmongo.DbMongo, "db_connect", mock.Mock()) - @mock.patch.object(dbmongo.DbMongo, "get_list") - def test_get_alarms(self, get_list): - get_list.return_value = [{ - 'uuid': '1', - 'name': 'name', - 'severity': 'severity', - 'threshold': 50, - 'operation': 'operation', - 'statistic': 'statistic', - 'tags': {}, - }] - - common_db_client = CommonDbClient(self.config) - alarms = common_db_client.get_alarms() - self.assertEqual('1', alarms[0].uuid) - - @mock.patch.object(dbmongo.DbMongo, "db_connect", mock.Mock()) - @mock.patch.object(dbmongo.DbMongo, "create") - def test_create_alarm(self, create): - alarm = Alarm('name', 'severity', 50.0, 'operation', 'statistic', 'metric', {}) - alarm.uuid = '1' - common_db_client = CommonDbClient(self.config) - common_db_client.create_alarm(alarm) - create.assert_called_with('alarms', {'tags': {}, 'threshold': 50.0, 'metric': 'metric', 'severity': 'severity', - 'statistic': 'statistic', 'name': 'name', 'uuid': '1'}) - - @mock.patch.object(dbmongo.DbMongo, "db_connect", mock.Mock()) - @mock.patch.object(dbmongo.DbMongo, "del_one") - def test_delete_alarm(self, delete): - common_db_client = CommonDbClient(self.config) - common_db_client.delete_alarm('1') - delete.assert_called_with('alarms', {'uuid': '1'}) diff --git a/osm_mon/tests/unit/evaluator/test_evaluator.py b/osm_mon/tests/unit/evaluator/test_evaluator.py index 43cec96..b20f602 100644 --- a/osm_mon/tests/unit/evaluator/test_evaluator.py +++ b/osm_mon/tests/unit/evaluator/test_evaluator.py @@ -39,7 +39,8 @@ class EvaluatorTest(TestCase): @mock.patch('multiprocessing.Process') @mock.patch.object(Evaluator, "notify_alarm") @mock.patch.object(EvaluatorService, "evaluate_alarms") - def test_evaluate(self, evaluate_alarms, notify_alarm, process): + @mock.patch('osm_mon.core.database.db') + def test_evaluate(self, db, evaluate_alarms, notify_alarm, process): mock_alarm = mock.Mock() mock_alarm.operation = 'gt' mock_alarm.threshold = 50.0 diff --git a/osm_mon/tests/unit/evaluator/test_evaluator_service.py b/osm_mon/tests/unit/evaluator/test_evaluator_service.py index bc93046..e09418d 100644 --- a/osm_mon/tests/unit/evaluator/test_evaluator_service.py +++ b/osm_mon/tests/unit/evaluator/test_evaluator_service.py @@ -24,6 +24,7 @@ from unittest import TestCase, mock from osm_mon.core.common_db import CommonDbClient from osm_mon.core.config import Config +from osm_mon.core.database import AlarmRepository, AlarmTag from osm_mon.core.message_bus_client import MessageBusClient from osm_mon.evaluator.backends.prometheus import PrometheusBackend from osm_mon.evaluator.evaluator import AlarmStatus @@ -148,7 +149,8 @@ class EvaluatorTest(TestCase): self.config = Config() @mock.patch.object(EvaluatorService, "_get_metric_value") - def test_evaluate_metric(self, get_metric_value): + @mock.patch('osm_mon.core.database.db') + def test_evaluate_metric(self, db, get_metric_value): mock_alarm = mock.Mock() mock_alarm.operation = 'gt' mock_alarm.threshold = 50.0 @@ -157,29 +159,33 @@ class EvaluatorTest(TestCase): service = EvaluatorService(self.config) service.queue = mock.Mock() - service._evaluate_metric(mock_alarm) + service._evaluate_metric(mock_alarm, {}) service.queue.put.assert_called_with((mock_alarm, AlarmStatus.ALARM)) service.queue.reset_mock() mock_alarm.operation = 'lt' - service._evaluate_metric(mock_alarm) + service._evaluate_metric(mock_alarm, {}) service.queue.put.assert_called_with((mock_alarm, AlarmStatus.OK)) service.queue.reset_mock() get_metric_value.return_value = None - service._evaluate_metric(mock_alarm) + service._evaluate_metric(mock_alarm, {}) service.queue.put.assert_called_with((mock_alarm, AlarmStatus.INSUFFICIENT)) @mock.patch('multiprocessing.Process') @mock.patch.object(EvaluatorService, "_evaluate_metric") @mock.patch.object(CommonDbClient, "get_vnfd") @mock.patch.object(CommonDbClient, "get_vnfr") - @mock.patch.object(CommonDbClient, "get_alarms") - def test_evaluate_alarms(self, alarm_list, get_vnfr, get_vnfd, evaluate_metric, process): + @mock.patch.object(AlarmRepository, "list") + @mock.patch('osm_mon.core.database.db') + def test_evaluate(self, db, alarm_list, get_vnfr, get_vnfd, evaluate_metric, process): mock_alarm = mock.Mock() mock_alarm.vdur_name = 'cirros_ns-1-cirros_vnfd-VM-1' mock_alarm.monitoring_param = 'cirros_vnf_memory_util' - mock_alarm.tags = {'name': 'value'} + mock_tag = AlarmTag() + mock_tag.name = 'name' + mock_tag.value = 'value' + mock_alarm.tags = [mock_tag] alarm_list.return_value = [mock_alarm] get_vnfr.return_value = vnfr_record_mock get_vnfd.return_value = vnfd_record_mock @@ -187,10 +193,11 @@ class EvaluatorTest(TestCase): evaluator = EvaluatorService(self.config) evaluator.evaluate_alarms() - process.assert_called_with(target=evaluate_metric, args=(mock_alarm,)) + process.assert_called_with(target=evaluate_metric, args=(mock_alarm, {'name': 'value'})) @mock.patch.object(PrometheusBackend, "get_metric_value") - def test_get_metric_value_prometheus(self, get_metric_value): + @mock.patch('osm_mon.core.database.db') + def test_get_metric_value_prometheus(self, db, get_metric_value): self.config.set('evaluator', 'backend', 'prometheus') evaluator = EvaluatorService(self.config) evaluator._get_metric_value('test', {}) -- 2.17.1