From d25e23623ab1e9bb24aae59259bc65bb8be60f7a Mon Sep 17 00:00:00 2001 From: wangyong <864072399@qq.com> Date: Sun, 22 Nov 2015 18:57:47 +0800 Subject: [PATCH 01/20] fix bugs --- jasset/asset_api.py | 6 ++--- jasset/views.py | 21 +++++++++--------- static/files/excels/asset.xlsx | Bin 24181 -> 0 bytes .../excels/cmdb_excel_2015_11_14_11_38.xlsx | Bin 6151 -> 0 bytes .../excels/cmdb_excel_2015_11_14_11_39.xlsx | Bin 6158 -> 0 bytes .../excels/cmdb_excel_2015_11_17_22_38.xlsx | Bin 4990 -> 0 bytes .../excels/cmdb_excel_2015_11_17_22_39.xlsx | Bin 4990 -> 0 bytes .../excels/cmdb_excel_2015_11_17_23_19.xlsx | Bin 4990 -> 0 bytes .../excels/cmdb_excel_2015_11_18_21_40.xlsx | Bin 4990 -> 0 bytes .../excels/cmdb_excel_2015_11_18_21_52.xlsx | Bin 4990 -> 0 bytes .../excels/cmdb_excel_2015_11_18_21_53.xlsx | Bin 6163 -> 0 bytes .../excels/cmdb_excel_2015_11_18_21_54.xlsx | Bin 5885 -> 0 bytes .../excels/cmdb_excel_2015_11_18_22_17.xlsx | Bin 5885 -> 0 bytes .../excels/cmdb_excel_2015_11_19_22_05.xlsx | Bin 6117 -> 0 bytes templates/jasset/asset_detail.html | 8 +++---- templates/jasset/asset_edit.html | 2 +- templates/jasset/asset_list.html | 1 + templates/jasset/idc_list.html | 8 +++---- templates/nav_li_profile.html | 4 ++-- 19 files changed, 26 insertions(+), 24 deletions(-) delete mode 100644 static/files/excels/asset.xlsx delete mode 100644 static/files/excels/cmdb_excel_2015_11_14_11_38.xlsx delete mode 100644 static/files/excels/cmdb_excel_2015_11_14_11_39.xlsx delete mode 100644 static/files/excels/cmdb_excel_2015_11_17_22_38.xlsx delete mode 100644 static/files/excels/cmdb_excel_2015_11_17_22_39.xlsx delete mode 100644 static/files/excels/cmdb_excel_2015_11_17_23_19.xlsx delete mode 100644 static/files/excels/cmdb_excel_2015_11_18_21_40.xlsx delete mode 100644 static/files/excels/cmdb_excel_2015_11_18_21_52.xlsx delete mode 100644 static/files/excels/cmdb_excel_2015_11_18_21_53.xlsx delete mode 100644 static/files/excels/cmdb_excel_2015_11_18_21_54.xlsx delete mode 100644 static/files/excels/cmdb_excel_2015_11_18_22_17.xlsx delete mode 100644 static/files/excels/cmdb_excel_2015_11_19_22_05.xlsx diff --git a/jasset/asset_api.py b/jasset/asset_api.py index 06c91a616..a37386a72 100644 --- a/jasset/asset_api.py +++ b/jasset/asset_api.py @@ -359,7 +359,6 @@ def ansible_record(asset, ansible_dic, username): old = asset_dic.get(field) new = ansible_dic.get(field) if unicode(old) != unicode(new): - print old, new, type(old), type(new) setattr(asset, field, value) asset.save() alert_dic[field] = [old, new] @@ -384,16 +383,17 @@ def excel_to_db(excel_file): row = table.row_values(row_num) if row: ip, port, hostname, use_default_auth, username, password, group = row - use_default_auth = 1 if use_default_auth == u'默认' else 0 if get_object(Asset, hostname=hostname): continue + use_default_auth = 1 if use_default_auth == u'默认' else 0 + password_encode = CRYPTOR.encrypt(password) if password else '' if hostname: asset = Asset(ip=ip, port=port, hostname=hostname, use_default_auth=use_default_auth, username=username, - password=password + password=password_encode ) asset.save() group_list = group.split('/') diff --git a/jasset/views.py b/jasset/views.py index af24d7de2..d6d0f1a3c 100644 --- a/jasset/views.py +++ b/jasset/views.py @@ -1,6 +1,5 @@ # coding:utf-8 -import ast from django.db.models import Q from jasset.asset_api import * from jumpserver.api import * @@ -95,8 +94,6 @@ def group_list(request): """ header_title, path1, path2 = u'查看资产组', u'资产管理', u'查看资产组' keyword = request.GET.get('keyword', '') - gid = request.GET.get('gid') - sid = request.GET.get('sid') asset_group_list = AssetGroup.objects.all() if keyword: @@ -211,6 +208,7 @@ def asset_edit(request): ip = request.POST.get('ip', '') hostname = request.POST.get('hostname', '') password = request.POST.get('password', '') + is_active = True if request.POST.get('is_active') == '1' else False use_default_auth = request.POST.get('use_default_auth', '') try: @@ -230,6 +228,7 @@ def asset_edit(request): if password_old != password: password_encode = CRYPTOR.encrypt(password) af_save.password = password_encode + af_save.is_active = True if is_active else False af_save.save() af_post.save_m2m() # asset_new = get_object(Asset, id=asset_id) @@ -250,6 +249,7 @@ def asset_list(request): """ asset list view """ + header_title, path1, path2 = u'查看资产', u'资产管理', u'查看资产' idc_all = IDC.objects.filter() asset_group_all = AssetGroup.objects.all() asset_types = ASSET_TYPE @@ -382,9 +382,8 @@ def asset_edit_batch(request): asset.save() if alert_list: - username = unicode(name) + ' - ' + u'批量' - print alert_list - AssetRecord.objects.create(asset=asset, username=username, content=alert_list) + recode_name = unicode(name) + ' - ' + u'批量' + AssetRecord.objects.create(asset=asset, username=recode_name, content=alert_list) return HttpResponse('ok') return my_render('jasset/asset_edit_batch.html', locals(), request) @@ -410,21 +409,21 @@ def asset_update(request): """ asset_id = request.GET.get('id', '') asset = get_object(Asset, id=asset_id) + name = request.session.get('username', 'admin') if not asset: return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id) - name = request.session.get('username', 'admin') if asset.use_default_auth: default = Setting.objects.all() if default: default = default[0] username = default.default_user - password = default.default_password + password = CRYPTOR.decrypt(default.default_password) port = default.default_port else: return HttpResponse(u'没有设置默认用户名和密码!') else: username = asset.username - password = asset.password + password = CRYPTOR.decrypt(asset.password) port = asset.port resource = [{"hostname": asset.ip, "port": port, @@ -436,7 +435,9 @@ def asset_update(request): asset_info = ansible_asset_info['result'][asset.ip] if asset_info: hostname = asset_info.get('hostname') - other_ip = ','.join(asset_info.get('other_ip')) + all_ip = asset_info.get('other_ip') + other_ip_list = all_ip.remove(asset.ip) if asset.ip in all_ip else [] + other_ip = ','.join(other_ip_list) if other_ip_list else '' cpu_type = asset_info.get('cpu_type')[1] cpu_cores = asset_info.get('cpu_cores') cpu = cpu_type + ' * ' + unicode(cpu_cores) diff --git a/static/files/excels/asset.xlsx b/static/files/excels/asset.xlsx deleted file mode 100644 index 1b92db891d85cb5736e2ed99e166078360ea90d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24181 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 diff --git a/static/files/excels/cmdb_excel_2015_11_14_11_38.xlsx b/static/files/excels/cmdb_excel_2015_11_14_11_38.xlsx deleted file mode 100644 index 7be819d9084f04688ea6b77427f045dc222d0c8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6151 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 JZGeA&`X49Qy6yk~ diff --git a/static/files/excels/cmdb_excel_2015_11_17_22_38.xlsx b/static/files/excels/cmdb_excel_2015_11_17_22_38.xlsx deleted file mode 100644 index 705c543475c0c947a28b36483792e3b1b833512d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4990 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 diff --git a/static/files/excels/cmdb_excel_2015_11_17_22_39.xlsx b/static/files/excels/cmdb_excel_2015_11_17_22_39.xlsx deleted file mode 100644 index 83ea97d23f2eeae373115ee6738bfbaae0d7d4ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4990 zcmZ{o1yIy&*T$D-sRd+_?(UNAZWg4G5LgzZ7bHcIZb^{_0TC%_lm-Q1B}AmVLpmkD zRln!;m3g1tng2brGuN5f-!k@7k0!Pr-e<4 zjUv0d>RGkO;tV zRRnGBGsq-Po)aV}0gNqWyQeCKhK;Bx)^BZm!7QSOF=4Gw44)7{sl#Kmi%jZNWA#au zJ9;m}<+SoSrXUab?0rK-hZ8%G0*d@VP>Yf|{B!JZEtL9OstC!h7Iw)q%UY{<{>rgn z8|vp+{7$uu6QGp9rwHdfO9@ykW(H+74EG!P@$fmY{!a;z<*4uB5|u5Q7`gXwXn?uU}pzP}igieZFhVSn#M4 z=M%NNY_`Ge8S3d=J30ym>1g_mRaOKqGuQDSWSoBq#xd4lO53Z6wJa6-hOcjVVmj&0~7yrifPk-Fkwf`HAiWolJ{#5_QMT z$knu_4^im}Z*`8{-Z)x>7qK((gp^6mAhKwAcl}$}xp(sLZD#+_U=|xcKb6?SW-W{Oi5hpz7_Zb&k zN@BsooxpDND#730zIUG_Oig55%UQH;MP*nHJ_hg6&yXj3hoHeC`5-&dG7GoUP+__{ z{XESun<5}oPa5Z+>>YKCnPsn<6oB@(37!MXap6c4NYDTPLZk_{t~L<3tD6V! zeK)tCE@bJ+xlAHmSOuf*@I&+2aDuG|C%EDEglJxgf*NI93?yo9B0*U)OD|l}eGO)a z)Wg8<){7a0XEELUfZ!wT*dmwH3qO3^jO z!>qvpfvT8%8UzHmhPOh+R$n{XlW6Nr7HTisa!Jp~)4PRg$q`pR-6B4XVsvFPjddBUv=o1A5dzfE(EI}Tt*ng&634$*&`X5$Kn z{&Fp`?`Q9X>_{pt`7elqF-ng`$A7rZV9cE})9ljcFL@xT-wPu;W zyZ7B7=_2T0XbmTUO9g1}5;8oA(_E3dE~Wm+%JglQ{c8vo4fjSyqFHZjun~-_fv%mE zs6cADPQH*Lq~HQP${+Mw;iNUy^zOkxRBA~U@^)5NK+(mwFgY;~4svl^qcRnD_)c?XjPs=3mebp=3-l-D7BgW6 zcZ<*Oy30Of7hNVW<}2sf^Cbd}^3fXZeV_y`R7Rhr)ORx2&_*y}=Gsi<@ALcnS@7zb zFD(f(GckK_zRa!0N*`!FOSpZ>nk$a?Lu3z|%)|0=&>84&rlMJ4W70^bSm*%2EhJMj z1y>hOsEenizONh9!~7@JvLu8{Cmo^E$tBK*IsqngeFHFSwDfal(se8dSvMOQp`cn) zD{ozrYT1xvvP;b8sduXcL0@dAMeBk>gijMe9|Hw<#mP2TnXg|olY%no*hu3l+^3@*yGE(nfFMDU^PQ^g;Fg@>b|}FoXSzgIRa=A)D>p z`LNf+Lqz^2t6S2lsNtDXM;*@%;NbjfQ{8ezibyNl$LDl#SW)|ga#J5F4~Tf8cQ(*@ z)?Yf!7XNLr`r)he(nOXu2OJ{kNc18PmUY;hDvGM^svd6C30X`{qH1QQs<#7=lFJl= z5c7?K4;lxU%Ci(FMB7SKKE9A8FGYFn{!&Cr?$x85+-ri06>nkIKudaVX$9kpleb$O z6wpiZ3+W_mB?3VEJL__z{gvn$&&n{kb4DE_kRzWTtJYImK8H zQd$u~HC@mz3BNBXOS(m0TQjBxo$NGcn6B<{ zSIfkLQ;(mw<`&6|94dhwW>PLvvXjk;7DUN3Ft5Mz2_8YW9_}ZK?<1OvJMi$!D7dIe zVa!J7toDKp-OL;HV*cs*hUY5j!^ihGtS)JeWd3%J>`YnzEd~IfNBO%^kV(nY9_kGJ z{rnY@woJ61O)8SL9B?YP)W_YD=qpbz6CN)J-Kr~@u6f-ZDOFiS?q8bLs`~1p0kvXG*?R|%pPW*!Zq#D&E2t={_9oRW z-zztXV3G#e6W5hV1YZ?C4=w0W3nbT3olGZoFrPe|eq{61J9W3r^y_rF(e5_t4)^Bl__kLDxT(HPBz5_}g4X6Ov&=(Gm>IMooe*f^bid~rBx*}{jGLhxwsTheTfl<(dV z?8&3+F~BUT&+ASsAr|6khVHe%ZmSGA0D07bE*^s>Cy6L(0m|52T?`+`s5Iaxy}{}< zco3l3wwZJeHU}~C>kb2^Vi$1So_UPSci8v4uxNLxk6GoPY+`#~srf~hkj3HGf?5pJ=Xq2LQPwpB zDY`(5vUn$a_qLv1x7k9)tcuc|K|TRiRWBGrZ@Kw;E5BC%gRU5Pk;k(!uw7>#p)~ac zPh5-8b6VjUYDu+Y;L_Q7%X!OAOLTy@0e8iu^KJZ*k=2Dv%OJ;-s@0nGwqR((bnUW zo;|RG$;#T)b_ZKG=H=k8I_(>JqM^RebV!K8 zb=_jZoEQlB*0xB;!4Tj;%$XB?uKcvX-kTIl!}fI}A?QP^=gJM=)wsEjF(g~FH{&aW zj=qE6x8||O;tGBA_txqWxZO3P98de&3XhNsDmGEq03izJNmd@-!6l=Do8;aOs`{ia z&*eXxxvm~Z8c;H)EA);}4@*cfNWSQ90-dd8idRcm+TGEd3PELPPFe})*9C9YIBZJW zZZbvb22CA&W+)#ytW|06nk;tfS8<+p za-TLk*UjjdM}t}pHWcrUTenc}qD4rj>m*|n@9C9rwfd$XtmhyYonC={(&<6+5r6 zk*;8xMM%1h$%V2uHvdEL_D*EHEMBYwR-F6yRTyHkPcn8RR_~Y!kE?`&1Ow3@-rt6} za&QN6;9`a|VhOkv;AO1XU1~C_7xy$jGXbl9!t_fx&3#xWrS*a{j-*!y;ULdGFuWe& z)fRX7rhLcqtS4|Kq`0nMcH%wr>r4KjJ5DZUuImX~_g~V%OfP!bY&EGPpZX5(WQG~7 z!jvpLz8+poD=aRDQhh9ciVW09HX92J3D_ z)ttd0iaP577Hne3);p`dp6xwngwHO?W8jZ{Im6Ax!4lf2Dc_>JPjJXmX@&Tx{n$>6 zG-PCkQx4OuZ9Rk3{W13VETn_ZN9HQT;Dp8)uzd8v!n%05vv8IkHyq5@CfZeHYYc$+#LUZ*8l(lpL!s3;s00p2kuSr&9U{5_!Q~U%^~)t`sV!fM_qRLIEEIHa)v08(rK zfClrcr@f$u6T;5b1_pC;75sGw3wS!%N5$#rvLpi@C zX*VTqLTMD%(O$!)MJqqw%DKCj@QiEzR8H_O`QoGO? zsT!qEt=!su9wMiecXJZ*RLI8b#qFW^wgcZnZxHNJ@hs^nVTcx1%{5h&RC^aK6hh0Rn~|^vXN|LLA-7*$7^RrocG@?#&0(Kqx(cB z<53!wy4`vhI<@{&cv{?B-P&aN)o>GngFew}?-)!+4-jnnR;@L6BrlJVC*enSROY~pvAyAKf;C_$30$Dqm+-0O3hg!AoJd0 ziW9Dv!8C<>F!l-(e=)+7rEoT4~E_IpevbOc&(~z zHvsxF@Mt+8Mx$c5yOoU=rEZMda*xmj_%?k^JvCIXO3Xb;12YK)b~R z9EJEqR;lpCl0NoT{oW3f9YDT?pfbdAgC<=NF-}Z*8@$V^+FD2<5zIIHv|2CjBF^)U z_9WaqFEXNdDW(QJQd5|$LmN|bzSOj>1rZ>P1Fh7!9C=<7_bVcdW|!vtTx&?ty-(cM zNg)65wfz_O6Q$Bg>h8Q{*F01IiMDvus(pOn*UQtmYiE|(OLzY^tylTWJ}1UB2&Qu= z{?jx|Cj{)5Yw@TjnBGx3Iw#6&;78r?C7gJUwE8BS%fmkfw2con0dZ7EUp7`I+y+{G zTUwcxbcI81%@m3Mz(W^&xy5E2O*t@0SR`@F8_GZElX%=*WnTIPlE);KCLsZ?Nu(zz z?|a}Z7ofwY>eKBIg=BpYUV%1+^uWL5=6w*?t{~T_X?eNhgv5Hd_=De&JjML^99GJB zSSXol3s?TR%LXAig90&;+jfc-ZgxFZ#;y^)@={Nc)e8T^YNpR!4SNU?ceCWDOEytI zfEN!N>!XTa>wyaA{nON)yBXh^KfFJ;$Hr6!li^zk8=?GU$$Y@;6ryzK%MwrHzq!Da z6tlbPRV}L(mtd@}s=jHcq}GMg3x~FKMqFHjFb1Ecd*Xg~h57|7gZ^fEJ2QAx2E&v9 z7XY}1VQQ-2KsmOt{G$2^DZ*iENaz z7gbAW5=17bmJUiKI!5+PengW6e6gCkjSP4pejE?_>@T`~hh`nkd708c4a#8UaY`g+ zQg6gsOxWqQL5BJBN%-)2X;Cp3D4HqcL0%Bb7`=_9Q~Dv%3)A<`U1r(B5A-Pt4EnU$P+Jg)QUC^}W~vAj)eV;%}_j5>dd0BNhY*EP~%w(p7d;cJX76%i?QNyyxVoeAoXh zu~Z=dHCHG4q^_T%EK_m(c5|`H=M-7m60A2auOy`9UO&suxg;xJ_7LathqCg^C_Fej zdbe?t4t7p^rX5*nT9$nRk8QXV2>Cv}b4>p?Zn}E9t{4n%OU%7P`up;Cb@Q@^x&8!Q zkf3WfDMZpSbHo!lGcn0nQo^prOhgdmK;j+LaALs;f45}L+X2h=LuB0W5L!{l=DXxP z=P-5u;pSqP!K%1Wfq9iiQTa!W;Mb`)G9G%&12XRo)eSDZ1l8Gn09i%$>iEjvY z#@p9jS(&6{CO&<_61o!`@IY>fMMa9&F1m%I!k}+d7*)ri$=K`CmjhDcLj>7|WmuJ% z(T#Rtq~)P3vsn@rNRVa!Qk)>WtYU zj*DCT@9#x{lMi1u??t7r<2Z-vJ%ZG=5Nzz;9q_f56yhI1O7a@mM}=-^zdk@QK+GdxvE8#;WvW`53eaPM#DXik*%-{AoOdi1{=1v4qR z*}xoNzn{N`qzz-Om(7tt=$_8?Z$;)hXqkG;EYVGW1K#4&#FNqwhN=+^*zLypsW`q`j ztLV(`T_(D5$_bUB-PjoVfSHYTE--js)1z%@`+;|ZV}I%%3TyPJMGp>KKQz^bx8KJB zC!^}?Zj~<^?$BMfQ~Kq7UG<~~KeK%9k-S}M@^z}rXnPZTi+_D)Y|}j*Twl{Hk-UA* zORrTE-Y-Xy*X0S!{OrnOg6DQoCAr!=&#prwW-WOC2-WQ9DbMF&E z?qy4PyX|gs;mna{ytp%m+LF0kPuCg9)@kznajYTwXzh5$?`(er+9-sRMD}dwTf$7X zwAao7{GVr+qktJ|&o^xZVmBzK*g97HJIvGN0JPzIx+H9xyi~Wb^RY(n>*9IZg{J~X zSPjrq-~oVU^LoN5*bKxjtUCmljG8BMj&U8HYqjZfyrCfhkAGo3XYp!*Oh`tgYcq?; z!6{z;#{Fw3N5z{@Hbq0l$<*Yjx;J-(S@A1<5)IF4ReW1GnR(n|UXi_4P9|A_q=q>T z(9Db6;vvi}JGR~uSaY_vXi|uNtIAE-qsa#>{;+c=i<^P|R=e=mIEjjIO?4*iAgId+ zee%^5*>KS>w(s5I7|)TOzr+j*uyF|)j6Yd}bZOVu6D)?H?{+9a&i_oO{iUczrC629%= zDVC}}??(J6=#*J}no&ya5V&}9+IZTy)fnOHVZdKL;c%UFco;pO0j)=LHeM^i> z7jf#POe8ybmnw*O^+PjD+1WU}cvk-To*l=Bla#kBLajWZE(l;QpK%Cf!NXRyW|OYF z_q6qdWM=lP;j*%p)g6Hrb-CH3X!~6Q?x%85ku9~YbVk$KDfa;*iOZhWw$rJD_Pyy4 zQbIVvKZVAEiVE%K$^kuFc!9vc zbf_pobe$uE?b*nLRyL@|zz|@6@X4!(nHn{s)gh{ZnpcxZKrTyGy%j%9vhPC`xtlN?8WfKY@8Bq|SW5z{arjB~CB zRCemi^ZCqVtg1&-`xejYihUH)BM?&zkT1L+$6^Ida&HVyy+4v&E~*U6PA%sBI`5$x zO-OI`ZKCIU4Mc4HMgcoway4h{^%`C9`Q`TFLRreQJ|+-#z~o*JTiNh_wMt9-M3Hl! zio=w>%arMBlm;o1<+ztmI-$_z6Y8 zaJVOQal1&euA+4e9^vB(_rZty!0W~z3Fw;M?OZG_xR-UjEz>#uJaF&@k8!=0H$bI# z^SdCgtqbTTF@6X;frxWHN&2$&xhA`MQCCBZF<7+|-#hL&=P6QJD}^_js#^zTE6>wE zv>NK(9KHXxY|HJW%YXSr5wcHqyq5FLx$xjEdq-2J)wqqvuUOzFXWiUZnv7x3y@s|j zf{m7QZ$bvpW`-kmXVQgPssp(>$P62b`$gLGD3hkA3=?KRbbq9Ve9h%YhP0pnb`N8q z<(bGJm&Cv`z~4lc6zTK6VMy>{h|v8WR(?bIxgz*Cul@!U*B_28OcJssqtxZgB}&9* z(SfR*HQ2{e=h`EHj}KaTWY*Mh*YbvXZd3UIf9%Q`t}hG}Glx%l73Ov#Ad4mCcSdYR zw;E-ra~?z%Yi=>x(u6%W(>63+i^^wotZTk0$6#lp)JhrWpbSJ7{CQ_Wl0q#*wTxQ${nC88k_$7LYa?YxAL+ zroW(*61-i}v!5vv@4l+D$ROBTNcP_2&bvro?-i~2_;U2lX4euBqJf1?h4bHcB^V;V zKK{>t9{+7~a<$6U`2V{G0O0@J6*Cw9Z}-o*sJQR`RR|k6f^z* zpZec4bya>fD*TaS;s3wE;c9`a!|$I0&IG^y`kztws`Tpg^+$RW_)B_q7Q0&DYIpxB tK#WmA|T<55% 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 diff --git a/static/files/excels/cmdb_excel_2015_11_18_21_52.xlsx b/static/files/excels/cmdb_excel_2015_11_18_21_52.xlsx deleted file mode 100644 index 8bbd9456543f283645bb753c789c6948ecafacb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4990 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 diff --git a/static/files/excels/cmdb_excel_2015_11_18_21_53.xlsx b/static/files/excels/cmdb_excel_2015_11_18_21_53.xlsx deleted file mode 100644 index 5a0f01efc9a11ff4354a7d6e843b8ddbeb183019..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6163 zcmZ`-1yqz<*B;5C8JIyjrMpukhOVKdL}KV15Rj5iX%LVu0Y^X@=}=NaN(pH}LP8Lb z{KtF0`+H@5-^^O)ta;bk`>c7M^Xzv&8>WVi0R{j7K){Pigp&Bj^L`<80N^1J06>m< z>f^-g?TT>pu!F-rJ$V1x_<4Mso#N7s5(;IⅈbD#0yGp=7nCqscjl8wbB#!IqdWC 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 diff --git a/static/files/excels/cmdb_excel_2015_11_18_21_54.xlsx b/static/files/excels/cmdb_excel_2015_11_18_21_54.xlsx deleted file mode 100644 index e0b025cac9a445a5c6018f8daea73774cca4c281..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5885 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 diff --git a/static/files/excels/cmdb_excel_2015_11_18_22_17.xlsx b/static/files/excels/cmdb_excel_2015_11_18_22_17.xlsx deleted file mode 100644 index 77ff51aa56da935c976498e0a86d0d55e9a32b62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5885 zcmZ`-1ys{*`yL>j1BP@-OG|@D45S7dDIk)gbEK3wDQOU1x}-!(k&+IjCLtm&hNU;*>%V6>xOFLT%!g600aQhYQ)_z>Oyu!YyhAF9{`}m zeCy{dhF3zzjrk)F|wBb9)M#9ro(l0BlM;t!;y}TtG(A*uG zru8fVYxHPV$l_~;(AL(B)co@N@*=L~>8^><8u%@bF_op;oE11T84mZ1+>PJqTa}Fo z<$$R2jSUmD!5*_L=zO}hDD*r}pB+9NNpM}aj;aUfpy1dcOFi}NxBdZg`M?pZv1Q0z50Vhv$jb%E1gQ1G`4D$4(-fxdeJLLKby zf~@B<_254HeA7}$m$VKMPagif1O-dNFc9?^bV9+>i5HX=VMmNj_HMhoj_RHTIsck0 z66erHv7ImjS6J!)zpZMoXc5|B&Q9_b7=9Tyj0|a;;12~VSz?7vR&%7ho_C!(+aTo7a7XyCcnKt{n&%JGG7mwb|)@IUYC6pHb=e z*8HkFnAR+DsKp}Wa?Sw#Bkj^x#jx*T0RViM)Fc0$c2;g~PQS7ZhSKg5rf5C@jmGQfT*2peqe;o9ek<~{wKbN@Q zM~zG*zXq?QO>Lsi8JA2oQiv%^g5`4*yMuAwY*|h5wLF43>SR60pw@8Oe7c(6{4OdZ z@g=M=RcSrS1pnLMtyO2_!p8zbt*hwjdvzlj^#v~2y!3_`1Z61BMEoYDm!5Hv5Kj>_ z`IM1vZ{N414p*0)gt$o6t=t_|L`)$1^fQ%c-=diDsoyC~way}JHScmc~Zr^EEV8p*>hUcKIvQ6n-#6nUa zMT^5r&qfm$kn9_EgqLlv_AChJ&mgd-36N`Ig5Ze>!q1L?seMm-O9b3T&kNz;YUlYg z65dHDjV=Z1@MC$Ew3c)ZM;A`@#Hcx?wN7~j`yPp5Ek|3v#0zpf3BEpa1H4nI}K!33pHu5 z6*r3^c@%!W@UX50g5=U3A-V+mOk>L;^Hx?gJh?If6 z;ME|L`78FZzBf9JUcvO5E(2QDMLz?(7NC_qQLH_1a?_?m>g}$#8ieVhvvh)o*rp;` zC9@3sH0RpZIZP|HKZRc-E3`yKw&hjpCs33n%Tec7V z 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 diff --git a/static/files/excels/cmdb_excel_2015_11_19_22_05.xlsx b/static/files/excels/cmdb_excel_2015_11_19_22_05.xlsx deleted file mode 100644 index 0c2778b8964fc3111d894fdf8beecd20e83e9953..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6117 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
    *bQr_yZc(sV7#>s=`|laD2|A(8oXXm z>Zs=Ls&^xO%U?(oHR-5t{Io77X4vKPw42C@F}#O!OLq=8GRl`Wp3FbmC8ob;XY)mi z?DM#U7fK3B)Dv=2N5Yx2z9$S^7wVGF$qt>C2)Nf;uTW2D{>iDSk)nt?g3}mO0DuU= zsez1>qZ`!G%~I<$TBg#(gbOk(dj2_Z76?5PxIm%jC_S{b4t*;GuBmW zH_EcDzTjb&I19TOmk8Rqin;fqlrTk5$p^>qYNgHF$+dS^oZRnDBf1x@nR6eJ&m8Cg z0M5T2HEu8Lp}(IoEm{tdvFd|6dP8tjJNPeSlCdhF;!X8rgjl*O-M-u2RS9&3s3YjdIw8~ud)f(24rOOZwfYfYlZj8f*K-E! zR@j%ZJAWhG!7@alE9Y^XK4Fx!TqSmqolv}loPd*Qov_?RS>CE)2>Xe*Q>ob)AX9VC z1_&lEEJbUyG}>#`!Ql+6(gAT($cr$6JV2aL97I2ZlFi|lK}2h^@+C_tgcuQ9x|P(c z%JrCNgZcd>lK^i&u2FxIZ;40Vg~uO_E)oOh#_5G4G$)5gZ0n4i9r=P(oHK58 zIINv4oNg6KRDZm?6?Jc{Ix|2V1mx)A$!t4ZUhR4<>RGiHG{W0?Z<9k~BO|@?r%-?m zaBUg?&~5&jmu)Tg(OP8*6n8Ey>tp1bWaGS5VOL)sMf*Has>_+om6Ssxfd`veu&q@~w5zM515H(n*Kv+h^ZpwKOu!v_&i|KqfjBlhMyfv;q8Biv~mX6QjjT3?X}i=~!K= ze^a?rT5_5ZUJS0LFp{`UbYqg@E?ak_ry2rfwl=vyt%lm3?HhkS@oI4#PCXhxnmp^! zv;u9P8mL))eu4r{9%ydjFJIF+pt$`^=$HF-(~}bHV;EKppd1jh0C ztYHI%7LQYhPs%nep5PSed-nkZk^yQ@N44{a;4tQNfL6sGqp51cFIc)E1X#T#>k`dg zH^ePoH!CZP9}~hPvcxB31&SAO_x>wMnt>iD~H zD>q6KuFt`@g!$}8FAh$uUi#cl0_I6Pi@GrQmm^L*7}tr#PU|5@W@SOE_+ZOL zvvRdHG_U&MzVRegn zhg%?@jJ*L#edRbpw#3WN3d|`xx7_30a<(*UlZk$>zycgpVF#7eABbeJP*L)K=J^^Y zSQ(+BM6DKL>{73VzZuIN?S&LKChKaT@?dM%Y(w^Q#a^Y2p&X`M5A%xZU_-2>%5%;1Zl?(Rnr%IN*vtC5Wf^@)<9b^4P%KHuOPS$W27$}Eb zFN`qXuv4*JzfV*`O_N)E{>aiwQqsJpC&;WRCmUzo{!p9cxzy{Zj>b+3-8r?CCxGvX zYo3-ibE#wYU(z8sKr4)wg?e1FGM`Q40|)oeg7ltpiplbJBC(pUkm0yc*fo}(c$M3X z2~arQcgUpOT$%wdHDiTqIR=sRS$<34IZxPD~J{;T#oePmjyJ@q=Uv3;_*CUD(sTm7e82c%Njf)3K?`2Yqhx zM!tSWk%QwDO{^_zJGPwfWCz^Xmc#lQi?7?;L$!~W^z(##EKQLKHa;0tc)GS8LJ-E8 zC_lc3MMeeFdrKNv)vG1V?meHesT57(Te6_R*TAib!6zFiUHBx9*1|Z+y)`uT$@lE? zhw{+u)RG5Zmpl}rfs_{C;DbAL5Wa2ZdBKio|5*b)RzM0gsn>=z3+Rd!BUMS8nhd7~S9TQyBTRphS$_J;!%U66e@~oCiW)nh90goD$s{{YA&QKM_1d2ut6W!O*OLv=arU9?tBiv?ZZ|5O74TRW+yo; z$hP94;0+7Uka=z!2R3AnFDzt(vGu~aBZWo16|=rHVGjtChxdqc9V5F;oNeiT zoDj_%@pJC~E|8xx-Nt>mwY0?mQAR>0M)}_hRRl@DU;Y8VF8^!2dN<15<0094h z3k383it;z#cfog;Du2K)5#Hm!tyu0xxNF+~L@-56&vz~SUG!b|_yW{8|vU+pZ*Vt1D&=2 diff --git a/templates/jasset/asset_detail.html b/templates/jasset/asset_detail.html index 4efb669a3..64b3e569f 100644 --- a/templates/jasset/asset_detail.html +++ b/templates/jasset/asset_detail.html @@ -29,14 +29,14 @@
    - - - - + + + +
    IP{{ asset.ip|default_if_none:"" }}
    主机名 {{ asset.hostname|default_if_none:"" }}
    IP{{ asset.ip|default_if_none:"" }}
    其他IP diff --git a/templates/jasset/asset_edit.html b/templates/jasset/asset_edit.html index 2aa3711cc..0c36be788 100644 --- a/templates/jasset/asset_edit.html +++ b/templates/jasset/asset_edit.html @@ -77,7 +77,7 @@
    - +
    diff --git a/templates/jasset/asset_list.html b/templates/jasset/asset_list.html index 26572fa27..2ecf8f2bf 100644 --- a/templates/jasset/asset_list.html +++ b/templates/jasset/asset_list.html @@ -142,6 +142,7 @@ {% include 'paginator.html' %} diff --git a/templates/jasset/idc_list.html b/templates/jasset/idc_list.html index 05812783c..60cbbf607 100644 --- a/templates/jasset/idc_list.html +++ b/templates/jasset/idc_list.html @@ -30,6 +30,7 @@
    添加IDC +
    - {% ifequal session_role_id 2 %} - - - {% endifequal %} +
    + Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries +
    {% include 'paginator.html' %}
    diff --git a/templates/nav_li_profile.html b/templates/nav_li_profile.html index 5a277698c..9f879ba6b 100644 --- a/templates/nav_li_profile.html +++ b/templates/nav_li_profile.html @@ -36,7 +36,7 @@ From 4cdc7f33ced3fe77d9bb31055a798f778ddbba8d Mon Sep 17 00:00:00 2001 From: ibuler Date: Sun, 22 Nov 2015 20:20:32 +0800 Subject: [PATCH 02/20] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- connect.py | 24 +++++++++++++++++++----- templates/nav.html | 2 -- templates/setting.html | 20 ++++++++++---------- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/connect.py b/connect.py index 05d84dd8f..23eb92bdb 100644 --- a/connect.py +++ b/connect.py @@ -504,24 +504,33 @@ class Nav(object): def search(self, str_r=''): gid_pattern = re.compile(r'^g\d+$') + # 获取用户授权的所有主机信息 if not self.user_perm: self.user_perm = get_group_user_perm(self.user) user_asset_all = self.user_perm.get('asset').keys() + # 搜索结果保存 user_asset_search = [] if str_r: + # 资产组组id匹配 if gid_pattern.match(str_r): - user_asset_search = list(Asset.objects.all()) + gid = int(str_r.lstrip('g')) + # 获取资产组包含的资产 + user_asset_search = get_object(AssetGroup, id=gid).asset_set.all() else: + # 匹配 ip, hostname, 备注 for asset in user_asset_all: - if str_r in asset.ip or str_r in str(asset.comment): + if str_r in asset.ip or str_r in str(asset.hostname) or str_r in str(asset.comment): user_asset_search.append(asset) else: + # 如果没有输入就展现所有 user_asset_search = user_asset_all self.search_result = dict(zip(range(len(user_asset_search)), user_asset_search)) print '\033[32m[%-3s] %-15s %-15s %-5s %-10s %s \033[0m' % ('ID', 'AssetName', 'IP', 'Port', 'Role', 'Comment') for index, asset in self.search_result.items(): + # 获取该资产信息 asset_info = get_asset_info(asset) + # 获取该资产包含的角色 role = [str(role.name) for role in self.user_perm.get('asset').get(asset).get('role')] if asset.comment: print '[%-3s] %-15s %-15s %-5s %-10s %s' % (index, asset.hostname, asset.ip, asset_info.get('port'), @@ -530,9 +539,11 @@ class Nav(object): print '[%-3s] %-15s %-15s %-5s %-10s' % (index, asset.hostname, asset.ip, asset_info.get('port'), role) print - @staticmethod - def print_asset_group(): - user_asset_group_all = AssetGroup.objects.all() + def print_asset_group(self): + """ + 打印用户授权的资产组 + """ + user_asset_group_all = get_group_user_perm(self.user).get('asset_group', []) print '\033[32m[%-3s] %-15s %s \033[0m' % ('ID', 'GroupName', 'Comment') for asset_group in user_asset_group_all: @@ -543,6 +554,9 @@ class Nav(object): print def exec_cmd(self): + """ + 批量执行命令 + """ self.search() while True: print "请输入主机名、IP或ansile支持的pattern, q退出" diff --git a/templates/nav.html b/templates/nav.html index df3e3d358..bbcf4c26e 100644 --- a/templates/nav.html +++ b/templates/nav.html @@ -36,8 +36,6 @@
  1. 系统角色
  2. -
  3. 权限审批
  4. -
  5. 授权记录
  6. diff --git a/templates/setting.html b/templates/setting.html index 55a49ba7c..7fa097150 100644 --- a/templates/setting.html +++ b/templates/setting.html @@ -29,7 +29,7 @@
  7. @@ -82,15 +82,15 @@
    -
    - - - - - - -
    组名
    -
    +{#
    #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{#
    组名
    #} +{#
    #} From 70db8c69d263a077146f0a3a806dae6f0a3c3b38 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sun, 22 Nov 2015 20:45:48 +0800 Subject: [PATCH 03/20] global SSH_FLAG to self.ssh_flag --- connect.py | 74 ++++++++++++++++++------------------------------------ 1 file changed, 24 insertions(+), 50 deletions(-) diff --git a/connect.py b/connect.py index b3440a628..00ece2f60 100644 --- a/connect.py +++ b/connect.py @@ -26,7 +26,6 @@ from jumpserver.settings import LOG_DIR from jperm.ansible_api import Command login_user = get_object(User, username=getpass.getuser()) -VIM_FLAG = False try: import termios @@ -52,23 +51,6 @@ def color_print(msg, color='red', exits=False): sys.exit() -def check_vim_status(command, ssh): - global SSH_TTY - print command - if command == '': - return True - else: - command_str= 'ps -ef |grep "%s" | grep "%s"|grep -v grep |wc -l' % (command,SSH_TTY) - print command_str - stdin, stdout, stderr = ssh.exec_command(command_str) - ps_num = stdout.read() - print ps_num - if int(ps_num) == 0: - return True - else: - return False - - class Tty(object): """ A virtual tty class @@ -86,6 +68,7 @@ class Tty(object): self.ssh = None self.connect_info = None self.login_type = 'ssh' + self.vim_flag = False @staticmethod def is_output(strings): @@ -95,25 +78,24 @@ class Tty(object): return True return False - @staticmethod - def deal_command(str_r): + def deal_command(self, str_r): """ - 处理命令中特殊字符 + 处理命令中特殊字符 """ - str_r = re.sub('\x07','',str_r) #删除响铃 - patch_char = re.compile('\x08\x1b\[C') #删除方向左右一起的按键 + str_r = re.sub('\x07', '', str_r) # 删除响铃 + patch_char = re.compile('\x08\x1b\[C') # 删除方向左右一起的按键 while patch_char.search(str_r): str_r = patch_char.sub('', str_r.rstrip()) - result_command = '' #最后的结果 - backspace_num = 0 #光标移动的个数 - reach_backspace_flag = False #没有检测到光标键则为true - pattern_str='' + result_command = '' # 最后的结果 + backspace_num = 0 # 光标移动的个数 + reach_backspace_flag = False # 没有检测到光标键则为true + pattern_str = '' while str_r: tmp = re.match(r'\s*\w+\s*', str_r) if tmp: - if reach_backspace_flag : - pattern_str +=str(tmp.group(0)) + if reach_backspace_flag: + pattern_str += str(tmp.group(0)) str_r = str_r[len(str(tmp.group(0))):] continue else: @@ -124,7 +106,7 @@ class Tty(object): tmp = re.match(r'\x1b\[K[\x08]*', str_r) if tmp: if backspace_num > 0: - if backspace_num > len(result_command) : + if backspace_num > len(result_command): result_command += pattern_str result_command = result_command[0:-backspace_num] else: @@ -134,8 +116,8 @@ class Tty(object): if del_len > 0: result_command = result_command[0:-del_len] reach_backspace_flag = False - backspace_num =0 - pattern_str='' + backspace_num = 0 + pattern_str = '' str_r = str_r[len(str(tmp.group(0))):] continue @@ -153,13 +135,13 @@ class Tty(object): else: break - if reach_backspace_flag : - pattern_str +=str_r[0] - else : + if reach_backspace_flag: + pattern_str += str_r[0] + else: result_command += str_r[0] str_r = str_r[1:] - if backspace_num > 0 : + if backspace_num > 0: result_command = result_command[0:-backspace_num] + pattern_str control_char = re.compile(r""" @@ -172,11 +154,10 @@ class Tty(object): [\x80-\x9f] | (?:\x1b\]0.*) | \[.*@.*\][\$#] | (.*mysql>.*) #匹配 所有控制字符 """, re.X) result_command = control_char.sub('', result_command.strip()) - global VIM_FLAG - if not VIM_FLAG: + if not self.vim_flag: if result_command.startswith('vi'): - VIM_FLAG = True - return result_command.decode('utf8',"ignore") + self.vim_flag = True + return result_command.decode('utf8', "ignore") else: return '' @@ -247,11 +228,6 @@ class Tty(object): """ 获取需要登陆的主机的信息和映射用户的账号密码 """ - - # 1. get ip, port - # 2. get 映射用户 - # 3. get 映射用户的账号,密码或者key - # self.connect_info = {'user': '', 'asset': '', 'ip': '', 'port': 0, 'role_name': '', 'role_pass': '', 'role_key': ''} asset_info = get_asset_info(self.asset) self.connect_info = {'user': self.user, 'asset': self.asset, 'ip': asset_info.get('ip'), 'port': int(asset_info.get('port')), 'role_name': self.role.name, @@ -340,8 +316,6 @@ class SshTty(Tty): data = '' chan_str = '' input_mode = False - global VIM_FLAG - try: tty.setraw(sys.stdin.fileno()) tty.setcbreak(sys.stdin.fileno()) @@ -358,7 +332,7 @@ class SshTty(Tty): x = self.channel.recv(1024) if len(x) == 0: break - if VIM_FLAG: + if self.vim_flag: chan_str += x sys.stdout.write(x) sys.stdout.flush() @@ -380,10 +354,10 @@ class SshTty(Tty): input_mode = True if str(x) in ['\r', '\n', '\r\n']: - if VIM_FLAG: + if self.vim_flag: match = pattern.search(chan_str) if match: - VIM_FLAG = False + self.vim_flag = False data = self.deal_command(data) if len(data) > 0: TtyLog(log=log, datetime=datetime.datetime.now(), cmd=data).save() From eb779e5bf64a3c153fb5160a27644898a895cd1d Mon Sep 17 00:00:00 2001 From: ibuler Date: Sun, 22 Nov 2015 21:59:07 +0800 Subject: [PATCH 04/20] =?UTF-8?q?=E4=BF=AE=E6=94=B9run=5Fwebsocket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- connect.py | 38 ++++++++------------------------------ run_websocket.py | 30 ++++++++++++++++++++---------- 2 files changed, 28 insertions(+), 40 deletions(-) diff --git a/connect.py b/connect.py index 00ece2f60..cf0824a7d 100644 --- a/connect.py +++ b/connect.py @@ -19,7 +19,7 @@ import struct, fcntl, signal, socket, select os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' if django.get_version() != '1.6': django.setup() -from jumpserver.api import ServerError, User, Asset, AssetGroup, get_object, mkdir, get_asset_info, get_role +from jumpserver.api import ServerError, User, Asset, PermRole, AssetGroup, get_object, mkdir, get_asset_info, get_role from jumpserver.api import logger, Log, TtyLog, get_role_key from jperm.perm_api import gen_resource, get_group_asset_perm, get_group_user_perm from jumpserver.settings import LOG_DIR @@ -69,6 +69,8 @@ class Tty(object): self.connect_info = None self.login_type = 'ssh' self.vim_flag = False + self.ps1_pattern = re.compile('\[.*@.*\][\$#]') + self.vim_data = '' @staticmethod def is_output(strings): @@ -161,27 +163,6 @@ class Tty(object): else: return '' - @staticmethod - def remove_control_char(str_r): - """ - 处理日志特殊字符 - """ - control_char = re.compile(r""" - \x1b[ #%()*+\-.\/]. | - \r | #匹配 回车符(CR) - (?:\x1b\[|\x9b) [ -?]* [@-~] | #匹配 控制顺序描述符(CSI)... Cmd - (?:\x1b\]|\x9d) .*? (?:\x1b\\|[\a\x9c]) | \x07 | #匹配 操作系统指令(OSC)...终止符或振铃符(ST|BEL) - (?:\x1b[P^_]|[\x90\x9e\x9f]) .*? (?:\x1b\\|\x9c) | #匹配 设备控制串或私讯或应用程序命令(DCS|PM|APC)...终止符(ST) - \x1b. #匹配 转义过后的字符 - [\x80-\x9f] #匹配 所有控制字符 - """, re.X) - backspace = re.compile(r"[^\b][\b]") - line_filtered = control_char.sub('', str_r.rstrip()) - while backspace.search(line_filtered): - line_filtered = backspace.sub('', line_filtered) - - return line_filtered - def get_log(self): """ Logging user command and output. @@ -312,9 +293,7 @@ class SshTty(Tty): log_file_f, log_time_f, log = self.get_log() old_tty = termios.tcgetattr(sys.stdin) pre_timestamp = time.time() - pattern = re.compile('\[.*@.*\][\$#]') data = '' - chan_str = '' input_mode = False try: tty.setraw(sys.stdin.fileno()) @@ -333,7 +312,7 @@ class SshTty(Tty): if len(x) == 0: break if self.vim_flag: - chan_str += x + self.vim_data += x sys.stdout.write(x) sys.stdout.flush() now_timestamp = time.time() @@ -352,21 +331,20 @@ class SshTty(Tty): if sys.stdin in r: x = os.read(sys.stdin.fileno(), 1) input_mode = True - if str(x) in ['\r', '\n', '\r\n']: if self.vim_flag: - match = pattern.search(chan_str) + match = self.ps1_pattern.search(self.vim_data) if match: self.vim_flag = False - data = self.deal_command(data) + data = self.deal_command(data)[0:200] if len(data) > 0: TtyLog(log=log, datetime=datetime.datetime.now(), cmd=data).save() else: - data = self.deal_command(data) + data = self.deal_command(data)[0:200] if len(data) > 0: TtyLog(log=log, datetime=datetime.datetime.now(), cmd=data).save() data = '' - chan_str = '' + self.vim_data = '' input_mode = False if len(x) == 0: diff --git a/run_websocket.py b/run_websocket.py index 9d565fe42..bb8a0a8ff 100644 --- a/run_websocket.py +++ b/run_websocket.py @@ -20,15 +20,9 @@ from tornado.websocket import WebSocketClosedError from tornado.options import define, options from pyinotify import WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE, IN_MODIFY, AsyncNotifier +import select -# from gevent import monkey -# monkey.patch_all() -# import gevent -# from gevent.socket import wait_read, wait_write -import struct, fcntl, signal, socket, select, fnmatch - -import paramiko -from connect import Tty +from connect import Tty, User, Asset, PermRole from connect import TtyLog, Log try: @@ -217,7 +211,10 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): username = self.get_argument('username', '') token = self.get_argument('token', '') print asset_name, username, token - self.term = WebTty('a', 'b') + user = User.objects.get(username='lastimac') + asset = Asset.objects.get(ip='192.168.244.129') + role = PermRole.objects.get(name='dev') + self.term = WebTty(user, asset, role) self.term.get_connection() self.term.channel = self.term.ssh.invoke_shell(term='xterm') WebTerminalHandler.tasks.append(MyThread(target=self.forward_outbound)) @@ -236,7 +233,17 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): if data.get('data'): self.term.input_mode = True if str(data['data']) in ['\r', '\n', '\r\n']: - TtyLog(log=self.log, datetime=datetime.datetime.now(), cmd=self.term.deal_command(self.term.data, self.term.ssh)).save() + if self.term.vim_flag: + match = self.term.ps1_pattern.search(self.term.vim_data) + if match: + self.term.vim_flag = False + vim_data = self.term.deal_command(self.term.vim_data)[0:200] + if len(data) > 0: + TtyLog(log=self.log, datetime=datetime.datetime.now(), cmd=vim_data).save() + + TtyLog(log=self.log, datetime=datetime.datetime.now(), + cmd=self.term.deal_command(self.term.data)[0:200]).save() + self.term.vim_data = '' self.term.data = '' self.term.input_mode = False self.term.channel.send(data['data']) @@ -267,6 +274,8 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): if not len(recv): return data += recv + if self.term.vim_flag: + self.term.vim_data += recv try: self.write_message(json.dumps({'data': data})) now_timestamp = time.time() @@ -290,4 +299,5 @@ if __name__ == '__main__': server.bind(options.port, options.host) # server.listen(options.port) server.start(num_processes=1) + print "Run server on %s:%s" % (options.host, options.port) tornado.ioloop.IOLoop.instance().start() From 5a3c11f619ac1ad572601d8e58f66a71644042b2 Mon Sep 17 00:00:00 2001 From: wangyong <864072399@qq.com> Date: Sun, 22 Nov 2015 23:53:25 +0800 Subject: [PATCH 05/20] asset update batch and crontab --- jasset/ansible_api.py | 459 ------------------------- jasset/asset_api.py | 63 ++++ jasset/models.py | 2 +- jasset/urls.py | 1 + jasset/views.py | 76 ++-- jumpserver/settings.py | 5 + templates/jasset/asset_detail.html | 6 + templates/jasset/asset_edit.html | 6 + templates/jasset/asset_edit_batch.html | 27 -- templates/jasset/asset_list.html | 51 ++- 10 files changed, 126 insertions(+), 570 deletions(-) delete mode 100644 jasset/ansible_api.py diff --git a/jasset/ansible_api.py b/jasset/ansible_api.py deleted file mode 100644 index 7041c7bf1..000000000 --- a/jasset/ansible_api.py +++ /dev/null @@ -1,459 +0,0 @@ -# -*- coding: utf-8 -*- - -from ansible.inventory.group import Group -from ansible.inventory.host import Host -from ansible.inventory import Inventory -from ansible.runner import Runner -from ansible.playbook import PlayBook - -from ansible import callbacks -from ansible import utils -from passlib.hash import sha512_crypt - -# from utils import get_rand_pass - -import random -import os.path -API_DIR = os.path.dirname(os.path.abspath(__file__)) -ANSIBLE_DIR = os.path.join(API_DIR, 'playbooks') - -def get_rand_pass(): - """ - get a reandom password. - """ - lower = [chr(i) for i in range(97,123)] - upper = [chr(i).upper() for i in range(97,123)] - digit = [str(i) for i in range(10)] - password_pool = [] - password_pool.extend(lower) - password_pool.extend(upper) - password_pool.extend(digit) - pass_list = [random.choice(password_pool) for i in range(1,14)] - pass_list.insert(random.choice(range(1,14)), '@') - pass_list.insert(random.choice(range(1,14)), random.choice(digit)) - password = ''.join(pass_list) - return password - -class AnsibleError(StandardError): - """ - the base AnsibleError which contains error(required), - data(optional) and message(optional). - 存储所有Ansible 异常对象 - """ - def __init__(self, error, data='', message=''): - super(AnsibleError, self).__init__(message) - self.error = error - self.data = data - self.message = message - - -class CommandValueError(AnsibleError): - """ - indicate the input value has error or invalid. - the data specifies the error field of input form. - 输入不合法 异常对象 - """ - def __init__(self, field, message=''): - super(CommandValueError, self).__init__('value:invalid', field, message) - - -class MyInventory(object): - """ - this is my ansible inventory object. - """ - def __init__(self, resource): - """ - resource的数据格式是一个列表字典,比如 - { - "group1": { - "hosts": [{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...], - "vars": {"var1": value1, "var2": value2, ...} - } - } - - 如果你只传入1个列表,这默认该列表内的所有主机属于my_group组,比如 - [{"hostname": "10.10.10.10", "port": "22", "username": "test", "password": "mypass"}, ...] - """ - self.resource = resource - self.inventory = Inventory() - self.gen_inventory() - - def add_group(self, hosts, groupname, groupvars=None): - """ - add hosts to a group - """ - my_group = Group(name=groupname) - - # if group variables exists, add them to group - if groupvars: - for key, value in groupvars.iteritems(): - my_group.set_variable(key, value) - - # add hosts to group - for host in hosts: - # set connection variables - hostname = host.get("hostname") - hostport = host.get("port") - username = host.get("username") - password = host.get("password") - my_host = Host(name=hostname, port=hostport) - my_host.set_variable('ansible_ssh_host', hostname) - my_host.set_variable('ansible_ssh_port', hostport) - my_host.set_variable('ansible_ssh_user', username) - my_host.set_variable('ansible_ssh_pass', password) - # set other variables - for key, value in host.iteritems(): - if key not in ["hostname", "port", "username", "password"]: - my_host.set_variable(key, value) - # add to group - my_group.add_host(my_host) - - self.inventory.add_group(my_group) - - def gen_inventory(self): - """ - add hosts to inventory. - """ - if isinstance(self.resource, list): - self.add_group(self.resource, 'my_group') - elif isinstance(self.resource, dict): - for groupname, hosts_and_vars in self.resource.iteritems(): - self.add_group(hosts_and_vars.get("hosts"), groupname, hosts_and_vars.get("vars")) - - -class Command(MyInventory): - """ - this is a command object for parallel execute command. - """ - def __init__(self, *args, **kwargs): - super(Command, self).__init__(*args, **kwargs) - self.results = '' - - def run(self, command, module_name="command", timeout=5, forks=10, group='my_group'): - """ - run command from andible ad-hoc. - command : 必须是一个需要执行的命令字符串, 比如 - 'uname -a' - """ - if module_name not in ["raw", "command", "shell"]: - raise CommandValueError("module_name", - "module_name must be of the 'raw, command, shell'") - hoc = Runner(module_name=module_name, - module_args=command, - timeout=timeout, - inventory=self.inventory, - subset=group, - forks=forks - ) - self.results = hoc.run() - - if self.stdout: - return {"ok": self.stdout} - else: - msg = [] - if self.stderr: - msg.append(self.stderr) - if self.dark: - msg.append(self.dark) - return {"failed": msg} - - @property - def raw_results(self): - """ - get the ansible raw results. - """ - return self.results - - @property - def exec_time(self): - """ - get the command execute time. - """ - result = {} - all = self.results.get("contacted") - for key, value in all.iteritems(): - result[key] = { - "start": value.get("start"), - "end" : value.get("end"), - "delta": value.get("delta"),} - return result - - @property - def stdout(self): - """ - get the comamnd standard output. - """ - result = {} - all = self.results.get("contacted") - for key, value in all.iteritems(): - result[key] = value.get("stdout") - return result - - @property - def stderr(self): - """ - get the command standard error. - """ - result = {} - all = self.results.get("contacted") - for key, value in all.iteritems(): - result[key] = { - "stderr": value.get("stderr"), - "warnings": value.get("warnings"),} - return result - - @property - def dark(self): - """ - get the dark results. - """ - return self.results.get("dark") - - -class Tasks(Command): - """ - this is a tasks object for include the common command. - """ - def __init__(self, *args, **kwargs): - super(Tasks, self).__init__(*args, **kwargs) - - def __run(self, module_args, module_name="command", timeout=5, forks=10, group='my_group'): - """ - run command from andible ad-hoc. - command : 必须是一个需要执行的命令字符串, 比如 - 'uname -a' - """ - hoc = Runner(module_name=module_name, - module_args=module_args, - timeout=timeout, - inventory=self.inventory, - subset=group, - forks=forks - ) - - self.results = hoc.run() - - @property - def msg(self): - """ - get the contacted and dark msg - """ - msg = {} - for result in ["contacted", "dark"]: - all = self.results.get(result) - for key, value in all.iteritems(): - if value.get("msg"): - msg[key] = value.get("msg") - return msg - - def push_key(self, user, key_path): - """ - push the ssh authorized key to target. - """ - module_args = 'user="%s" key="{{ lookup("file", "%s") }}"' % (user, key_path) - self.__run(module_args, "authorized_key") - - return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"} - - def del_key(self, user, key_path): - """ - push the ssh authorized key to target. - """ - module_args = 'user="%s" key="{{ lookup("file", "%s") }}" state="absent"' % (user, key_path) - self.__run(module_args, "authorized_key") - - return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"} - - def add_user(self, username, password): - """ - add a host user. - """ - encrypt_pass = sha512_crypt.encrypt(password) - module_args = 'name=%s shell=/bin/bash password=%s' % (username, encrypt_pass) - self.__run(module_args, "user") - - return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"} - - def add_multi_user(self, *args): - """ - add multi user - :param args: - user - :return: - """ - results = {} - users = {} - action = results["action_info"] = {} - for user in args: - users[user] = get_rand_pass() - for user, password in users.iteritems(): - ret = self.add_user(user, password) - action[user] = ret - results["user_info"] = users - - return results - - def del_user(self, username): - """ - delete a host user. - """ - module_args = 'name=%s state=absent remove=yes move_home=yes force=yes' % (username) - self.__run(module_args, "user") - - return {"status": "failed","msg": self.msg} if self.msg else {"status": "ok"} - - def add_init_users(self): - """ - add initail users: SA, DBA, DEV - """ - results = {} - action = results["action_info"] = {} - users = {"SA": get_rand_pass(), "DBA": get_rand_pass(), "DEV": get_rand_pass()} - for user, password in users.iteritems(): - ret = self.add_user(user, password) - action[user] = ret - results["user_info"] = users - - return results - - def del_init_users(self): - """ - delete initail users: SA, DBA, DEV - """ - results = {} - action = results["action_info"] = {} - for user in ["SA", "DBA", "DEV"]: - ret = self.del_user(user) - action[user] = ret - return results - - def get_host_info(self): - """ - use the setup module get host informations - :return: - all_ip is list - processor_count is int - system_dist_version is string - system_type is string - disk is dict (device_name: device_size} - system_dist is string - processor_type is string - default_ip is string - hostname is string - product_sn is string - memory_total is int (MB) - default_mac is string - product_name is string - """ - self.__run('', 'setup') - - result = {} - all = self.results.get("contacted") - for key, value in all.iteritems(): - setup =value.get("ansible_facts") - # get disk informations - disk_all = setup.get("ansible_devices") - disk_need = {} - for disk_name, disk_info in disk_all.iteritems(): - if disk_name.startswith('sd') or disk_name.startswith('hd') or disk_name.startswith('vd'): - disk_need[disk_name] = disk_info.get("size") - - result[key] = { - "other_ip": setup.get("ansible_all_ipv4_addresses"), - "hostname": setup.get("ansible_hostname" ), - "ip": setup.get("ansible_default_ipv4").get("address"), - "mac": setup.get("ansible_default_ipv4").get("macaddress"), - "brand": setup.get("ansible_product_name"), - "cpu_type": setup.get("ansible_processor"), - "cpu_cores": setup.get("ansible_processor_count"), - "memory": setup.get("ansible_memtotal_mb"), - "disk": disk_need, - "system_type": setup.get("ansible_distribution"), - "system_version": setup.get("ansible_distribution_version"), - "asset_type": setup.get("ansible_system"), - "sn": setup.get("ansible_product_serial") - } - - return {"status": "failed", "msg": self.msg} if self.msg else {"status": "ok", "result": result} - - -class CustomAggregateStats(callbacks.AggregateStats): - """ - Holds stats about per-host activity during playbook runs. - """ - def __init__(self): - super(CustomAggregateStats, self).__init__() - self.results = [] - - def compute(self, runner_results, setup=False, poll=False, - ignore_errors=False): - """ - Walk through all results and increment stats. - """ - super(CustomAggregateStats, self).compute(runner_results, setup, poll, - ignore_errors) - - self.results.append(runner_results) - - - def summarize(self, host): - """ - Return information about a particular host - """ - summarized_info = super(CustomAggregateStats, self).summarize(host) - - # Adding the info I need - summarized_info['result'] = self.results - - return summarized_info - - -class MyPlaybook(MyInventory): - """ - this is my playbook object for execute playbook. - """ - def __init__(self, *args, **kwargs): - super(MyPlaybook, self).__init__(*args, **kwargs) - - - def run(self, playbook_relational_path, extra_vars=None): - """ - run ansible playbook, - only surport relational path. - """ - stats = callbacks.AggregateStats() - playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY) - runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY) - playbook_path = os.path.join(ANSIBLE_DIR, playbook_relational_path) - - pb = PlayBook( - playbook = playbook_path, - stats = stats, - callbacks = playbook_cb, - runner_callbacks = runner_cb, - inventory = self.inventory, - extra_vars = extra_vars, - check=False) - - self.results = pb.run() - - @property - def raw_results(self): - """ - get the raw results after playbook run. - """ - return self.results - - -class App(MyPlaybook): - """ - this is a app object for inclue the common playbook. - """ - def __init__(self, *args, **kwargs): - super(App, self).__init__(*args, **kwargs) - - -if __name__ == "__main__": - pass - - diff --git a/jasset/asset_api.py b/jasset/asset_api.py index a37386a72..9cc375509 100644 --- a/jasset/asset_api.py +++ b/jasset/asset_api.py @@ -4,6 +4,8 @@ import xlsxwriter from django.db.models import AutoField from jumpserver.api import * from jasset.models import ASSET_STATUS, ASSET_TYPE, ASSET_ENV, IDC, AssetRecord +from jperm.ansible_api import MyRunner +from jperm.perm_api import gen_resource def group_add_asset(group, asset_id=None, asset_ip=None): @@ -406,3 +408,64 @@ def excel_to_db(excel_file): asset.group = group_instance asset.save() return True + + +def get_ansible_asset_info(asset_ip, setup_info): + disk_all = setup_info.get("ansible_devices") + disk_need = {} + for disk_name, disk_info in disk_all.iteritems(): + if disk_name.startswith('sd') or disk_name.startswith('hd') or disk_name.startswith('vd'): + disk_need[disk_name] = disk_info.get("size") + + all_ip = setup_info.get("ansible_all_ipv4_addresses") + other_ip_list = all_ip.remove(asset_ip) if asset_ip in all_ip else [] + other_ip = ','.join(other_ip_list) if other_ip_list else '' + # hostname = setup_info.get("ansible_hostname") + # ip = setup_info.get("ansible_default_ipv4").get("address") + mac = setup_info.get("ansible_default_ipv4").get("macaddress") + brand = setup_info.get("ansible_product_name") + cpu_type = setup_info.get("ansible_processor")[1] + cpu_cores = setup_info.get("ansible_processor_count") + cpu = cpu_type + ' * ' + unicode(cpu_cores) + memory = setup_info.get("ansible_memtotal_mb") + disk = disk_need + system_type = setup_info.get("ansible_distribution") + system_version = setup_info.get("ansible_distribution_version") + # asset_type = setup_info.get("ansible_system") + sn = setup_info.get("ansible_product_serial") + asset_info = [other_ip, mac, cpu, memory, disk, sn, system_type, system_version, brand] + + return asset_info + + +def asset_ansible_update(obj_list, name=''): + resource = gen_resource(obj_list) + ansible_instance = MyRunner(resource) + ansible_asset_info = ansible_instance.run(module_name='setup', pattern='*') + for asset in obj_list: + try: + setup_info = ansible_asset_info['contacted'][asset.hostname]['ansible_facts'] + except KeyError: + continue + else: + asset_info = get_ansible_asset_info(asset.ip, setup_info) + other_ip, mac, cpu, memory, disk, sn, system_type, system_version, brand = asset_info + asset_dic = {"other_ip": other_ip, + "mac": mac, + "cpu": cpu, + "memory": memory, + "disk": disk, + "sn": sn, + "system_type": system_type, + "system_version": system_version, + "brand": brand + } + + ansible_record(asset, asset_dic, name) + + +def asset_ansible_update_all(): + name = u'定时更新' + asset_all = Asset.objects.all() + asset_ansible_update(asset_all, name) + diff --git a/jasset/models.py b/jasset/models.py index 159d72254..4f0ce5107 100644 --- a/jasset/models.py +++ b/jasset/models.py @@ -73,7 +73,7 @@ class Asset(models.Model): memory = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'内存') disk = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'硬盘') system_type = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"系统类型") - system_version = models.CharField(max_length=8, blank=True, null=True, verbose_name=u"版本号") + system_version = models.CharField(max_length=8, blank=True, null=True, verbose_name=u"系统版本号") cabinet = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'机柜号') position = models.IntegerField(blank=True, null=True, verbose_name=u'机器位置') number = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'资产编号') diff --git a/jasset/urls.py b/jasset/urls.py index 10d6dafc7..8fcbcdea4 100644 --- a/jasset/urls.py +++ b/jasset/urls.py @@ -11,6 +11,7 @@ urlpatterns = patterns('', url(r"^asset_detail/$", asset_detail), url(r'^asset_edit/$', asset_edit), url(r'^asset_update/$', asset_update), + url(r'^asset_update_batch/$', asset_update_batch), # url(r'^search/$', host_search), # url(r"^show_all_ajax/$", show_all_ajax), url(r'^group_add/$', group_add), diff --git a/jasset/views.py b/jasset/views.py index 9bbff91de..54bc576a7 100644 --- a/jasset/views.py +++ b/jasset/views.py @@ -6,7 +6,8 @@ from jumpserver.api import * from jumpserver.models import Setting from jasset.forms import AssetForm, IdcForm from jasset.models import Asset, IDC, AssetGroup, ASSET_TYPE, ASSET_STATUS -from ansible_api import Tasks +from jperm.ansible_api import Tasks, MyRunner +from jperm.perm_api import gen_resource @require_role('admin') @@ -197,7 +198,7 @@ def asset_edit(request): header_title, path1, path2 = u'修改资产', u'资产管理', u'修改资产' asset_id = request.GET.get('id', '') - username = request.session.get('username', 'admin') + username = request.user.username asset = get_object(Asset, id=asset_id) if asset: password_old = asset.password @@ -311,7 +312,7 @@ def asset_list(request): @require_role('admin') def asset_edit_batch(request): af = AssetForm() - name = request.session.get('username', 'admin') + name = request.user.username asset_group_all = AssetGroup.objects.all() if request.method == 'POST': @@ -409,55 +410,30 @@ def asset_update(request): """ asset_id = request.GET.get('id', '') asset = get_object(Asset, id=asset_id) - name = request.session.get('username', 'admin') + name = request.user.username if not asset: return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id) - if asset.use_default_auth: - default = Setting.objects.all() - if default: - default = default[0] - username = default.default_user - password = CRYPTOR.decrypt(default.default_password) - port = default.default_port - else: - return HttpResponse(u'没有设置默认用户名和密码!') else: - username = asset.username - password = CRYPTOR.decrypt(asset.password) - port = asset.port - - resource = [{"hostname": asset.ip, "port": port, - "username": username, "password": password}] - - ansible_instance = Tasks(resource) - ansible_asset_info = ansible_instance.get_host_info() - if ansible_asset_info['status'] == 'ok': - asset_info = ansible_asset_info['result'][asset.ip] - if asset_info: - hostname = asset_info.get('hostname') - all_ip = asset_info.get('other_ip') - other_ip_list = all_ip.remove(asset.ip) if asset.ip in all_ip else [] - other_ip = ','.join(other_ip_list) if other_ip_list else '' - cpu_type = asset_info.get('cpu_type')[1] - cpu_cores = asset_info.get('cpu_cores') - cpu = cpu_type + ' * ' + unicode(cpu_cores) - memory = asset_info.get('memory') - disk = asset_info.get('disk') - sn = asset_info.get('sn') - brand = asset_info.get('brand') - system_type = asset_info.get('system_type') - system_version = asset_info.get('system_version') - - asset_dic = {"hostname": hostname, "other_ip": other_ip, "cpu": cpu, - "memory": memory, "disk": disk, "system_type": system_type, - "system_version": system_version, "brand": brand, "sn": sn - } - - ansible_record(asset, asset_dic, name) - + asset_ansible_update(asset_list, name) return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id) +@require_role('admin') +def asset_update_batch(request): + if request.method == 'POST': + asset_list = [] + name = unicode(request.user.username) + ' - ' + u'自动更新' + asset_id_all = unicode(request.POST.get('asset_id_all', '')) + asset_id_all = asset_id_all.split(',') + for asset_id in asset_id_all: + asset = get_object(Asset, id=asset_id) + if asset: + asset_list.append(asset) + asset_ansible_update(asset_list, name) + return HttpResponse(u'批量更新成功!') + return HttpResponse(u'批量更新成功!') + + @require_role('admin') def idc_add(request): """ @@ -478,9 +454,7 @@ def idc_add(request): return HttpResponseRedirect("/jasset/idc_list/") else: idc_form = IdcForm() - return render_to_response('jasset/idc_add.html', - locals(), - context_instance=RequestContext(request)) + return my_render('jasset/idc_add.html', locals(), request) @require_role('admin') @@ -496,9 +470,7 @@ def idc_list(request): else: posts = IDC.objects.exclude(name='ALL').order_by('id') contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) - return render_to_response('jasset/idc_list.html', - locals(), - context_instance=RequestContext(request)) + return my_render('jasset/idc_list.html', locals(), request) @require_role('admin') diff --git a/jumpserver/settings.py b/jumpserver/settings.py index be8464d38..fa8431272 100644 --- a/jumpserver/settings.py +++ b/jumpserver/settings.py @@ -66,6 +66,7 @@ INSTALLED_APPS = ( 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.humanize', + 'django_crontab', 'bootstrapform', 'jumpserver', 'juser', @@ -149,3 +150,7 @@ USE_TZ = False STATIC_URL = '/static/' BOOTSTRAP_COLUMN_COUNT = 10 + +CRONJOBS = [ + ('0 1 * * *', 'jasset.asset_api.asset_ansible_update_all') +] diff --git a/templates/jasset/asset_detail.html b/templates/jasset/asset_detail.html index 64b3e569f..bc38235ed 100644 --- a/templates/jasset/asset_detail.html +++ b/templates/jasset/asset_detail.html @@ -11,9 +11,15 @@
    {{ asset.ip }} {% endblock %} \ No newline at end of file From a9196ef1499d64d5ef94a8148a746442ed7e1ee4 Mon Sep 17 00:00:00 2001 From: wangyong <864072399@qq.com> Date: Mon, 23 Nov 2015 11:12:14 +0800 Subject: [PATCH 06/20] merge cmdb | add asset update batch and crontab --- static/files/excels/asset.xlsx | Bin 0 -> 24181 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 static/files/excels/asset.xlsx diff --git a/static/files/excels/asset.xlsx b/static/files/excels/asset.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..1b92db891d85cb5736e2ed99e166078360ea90d1 GIT binary patch literal 24181 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 literal 0 HcmV?d00001 From ee218a5fedbb81a5938485534f895cd409aa8148 Mon Sep 17 00:00:00 2001 From: kelianchun_miller <360271747@qq.com> Date: Mon, 23 Nov 2015 12:47:02 +0800 Subject: [PATCH 07/20] update connect.py --- connect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connect.py b/connect.py index 00ece2f60..13649c270 100644 --- a/connect.py +++ b/connect.py @@ -155,7 +155,7 @@ class Tty(object): """, re.X) result_command = control_char.sub('', result_command.strip()) if not self.vim_flag: - if result_command.startswith('vi'): + if result_command.startswith('vi') or result_command.startswith('fg'): self.vim_flag = True return result_command.decode('utf8', "ignore") else: From f49a92e742fe8513c0e3677cbfc023ae8452c8e6 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 23 Nov 2015 15:34:28 +0800 Subject: [PATCH 08/20] =?UTF-8?q?webscoket=E6=8E=88=E6=9D=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- connect.py | 3 ++- jlog/views.py | 7 ++---- jperm/perm_api.py | 9 ++++++++ run_websocket.py | 55 ++++++++++++++++++++++++++++++++++++----------- 4 files changed, 55 insertions(+), 19 deletions(-) diff --git a/connect.py b/connect.py index e84aa141e..d16d9d7b6 100644 --- a/connect.py +++ b/connect.py @@ -19,9 +19,10 @@ import struct, fcntl, signal, socket, select os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' if django.get_version() != '1.6': django.setup() +from django.contrib.sessions.models import Session from jumpserver.api import ServerError, User, Asset, PermRole, AssetGroup, get_object, mkdir, get_asset_info, get_role from jumpserver.api import logger, Log, TtyLog, get_role_key -from jperm.perm_api import gen_resource, get_group_asset_perm, get_group_user_perm +from jperm.perm_api import gen_resource, get_group_asset_perm, get_group_user_perm, user_have_perm from jumpserver.settings import LOG_DIR from jperm.ansible_api import Command diff --git a/jlog/views.py b/jlog/views.py index 0e3ee2ade..d5f38852d 100644 --- a/jlog/views.py +++ b/jlog/views.py @@ -104,10 +104,7 @@ def log_record(request): def web_terminal(request): - #username = get_session.get('username', '') - token = request.COOKIES.get('sessionid') - username = request.user.username - asset_name = '127.0.0.1' - web_terminal_uri = 'ws://%s/terminal?username=%s&asset_name=%s&token=%s' % (WEB_SOCKET_HOST, username, asset_name, token) + asset_id = 15 + web_terminal_uri = 'ws://%s/terminal?asset_id=%s' % (WEB_SOCKET_HOST, asset_id) return render_to_response('jlog/web_terminal.html', locals()) diff --git a/jperm/perm_api.py b/jperm/perm_api.py index f79040c60..2bd6de632 100644 --- a/jperm/perm_api.py +++ b/jperm/perm_api.py @@ -132,6 +132,15 @@ def get_group_asset_perm(ob): return perm +def user_have_perm(user, asset): + user_perm_all = get_group_user_perm(user) + user_assets = user_perm_all.get('asset').keys() + if asset in user_assets: + return user_perm_all.get('asset').get(asset).get('role') + else: + return False + + def gen_resource(ob, ex='', perm=None): """ ob为用户或资产列表或资产queryset, 如果同时输入用户和资产,则获取用户在这些资产上的信息 diff --git a/run_websocket.py b/run_websocket.py index bb8a0a8ff..d2b76e36c 100644 --- a/run_websocket.py +++ b/run_websocket.py @@ -23,7 +23,7 @@ from pyinotify import WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE import select from connect import Tty, User, Asset, PermRole -from connect import TtyLog, Log +from connect import TtyLog, Log, Session, user_have_perm try: import simplejson as json @@ -37,14 +37,44 @@ define("host", default='0.0.0.0', help="run port on", type=str) def require_auth(func): def _deco(request, *args, **kwargs): - username = request.get_argument('username', '') - asset_name = request.get_argument('asset_name', '') - token = request.get_argument('token', '') - print username, asset_name, token - client = tornado.httpclient.HTTPClient() - # response = client.fetch('http://some/url') + urllib.urlencode({'username': username, - # 'asset_name': asset_name, 'token': token}) - # return request.close() + if request.get_cookie('sessionid'): + session_key = request.get_cookie('sessionid') + else: + session_key = request.get_secure_cookie('sessionid') + + print "session: " + session_key + + if not session_key: + print('Auth Failed') + request.close() + + session = Session.objects.filter(session_key=session_key) + if not session: + print('Auth Failed') + request.close() + else: + session = session[0] + uid = session.get_decoded().get('_auth_user_id') + user = User.objects.filter(id=uid) + asset_id = request.get_argument('asset_id', 9999) + + asset = Asset.objects.filter(id=asset_id) + if asset: + asset = asset[0] + request.asset = asset + role = user_have_perm(user, asset) + request.role = role + else: + role = '' + + if user: + user = user[0] + request.user = user + + else: + print("No session user.") + request.close() + return func(request, *args, **kwargs) return _deco @@ -200,6 +230,8 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): self.log_time_f = None self.log = None self.id = 0 + self.asset = None + self.user = None super(WebTerminalHandler, self).__init__(*args, **kwargs) def check_origin(self, origin): @@ -207,10 +239,7 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): @require_auth def open(self): - asset_name = self.get_argument('asset_name', '') - username = self.get_argument('username', '') - token = self.get_argument('token', '') - print asset_name, username, token + print self.user, self.asset user = User.objects.get(username='lastimac') asset = Asset.objects.get(ip='192.168.244.129') role = PermRole.objects.get(name='dev') From 483ca9677c49cab9b74b9ba8164e11993f384283 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 23 Nov 2015 18:39:38 +0800 Subject: [PATCH 09/20] =?UTF-8?q?=E8=B5=84=E4=BA=A7=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jlog/urls.py | 1 + jlog/views.py | 15 +++++++++-- jumpserver/templatetags/mytags.py | 9 +++++++ run_websocket.py | 19 ++++++++++---- templates/jasset/asset_list.html | 42 ++++++++++++++++++++++++++++++- 5 files changed, 78 insertions(+), 8 deletions(-) diff --git a/jlog/urls.py b/jlog/urls.py index 0058bcfe6..deb2902b4 100644 --- a/jlog/urls.py +++ b/jlog/urls.py @@ -9,4 +9,5 @@ urlpatterns = patterns('', url(r'^log_kill/', log_kill), url(r'^record/$', log_record), url(r'^web_terminal/$', web_terminal), + url(r'^get_role_name/$', get_role_name), ) \ No newline at end of file diff --git a/jlog/views.py b/jlog/views.py index d5f38852d..20b7f7c98 100644 --- a/jlog/views.py +++ b/jlog/views.py @@ -4,6 +4,7 @@ from django.template import RequestContext from django.shortcuts import render_to_response from jumpserver.api import * +from jperm.perm_api import user_have_perm from django.http import HttpResponseNotFound from jlog.log_api import renderTemplate @@ -103,8 +104,18 @@ def log_record(request): return HttpResponse('无日志记录!') +def get_role_name(request): + asset_id = request.GET.get('id', 9999) + asset = get_object(Asset, id=asset_id) + if asset: + role = user_have_perm(request.user, asset=asset) + return HttpResponse(','.join(list(role))) + return HttpResponse('dev,sa') + + +@require_role() def web_terminal(request): - asset_id = 15 - web_terminal_uri = 'ws://%s/terminal?asset_id=%s' % (WEB_SOCKET_HOST, asset_id) + asset_id = request.GET.get('id') + web_terminal_uri = 'ws://%s/terminal?id=%s&role=dev' % (WEB_SOCKET_HOST, asset_id) return render_to_response('jlog/web_terminal.html', locals()) diff --git a/jumpserver/templatetags/mytags.py b/jumpserver/templatetags/mytags.py index 5af20cdd6..c8f5debde 100644 --- a/jumpserver/templatetags/mytags.py +++ b/jumpserver/templatetags/mytags.py @@ -237,3 +237,12 @@ def key_exist(username): return True else: return False + + +@register.filter(name='check_role') +def check_role(asset_id, user): + """ + ssh key is exist or not + """ + return user + diff --git a/run_websocket.py b/run_websocket.py index d2b76e36c..27420b4ea 100644 --- a/run_websocket.py +++ b/run_websocket.py @@ -56,7 +56,7 @@ def require_auth(func): session = session[0] uid = session.get_decoded().get('_auth_user_id') user = User.objects.filter(id=uid) - asset_id = request.get_argument('asset_id', 9999) + asset_id = int(request.get_argument('id', 9999)) asset = Asset.objects.filter(id=asset_id) if asset: @@ -240,10 +240,19 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): @require_auth def open(self): print self.user, self.asset - user = User.objects.get(username='lastimac') - asset = Asset.objects.get(ip='192.168.244.129') - role = PermRole.objects.get(name='dev') - self.term = WebTty(user, asset, role) + role_name = self.get_argument('role', 'root') + roles = user_have_perm(self.user, self.asset) + login_role = '' + for role in roles: + if role.name == role_name: + login_role = role + break + if not login_role: + print "no role" + self.close() + return + # Todo: 判断 + self.term = WebTty(self.user, self.asset, login_role) self.term.get_connection() self.term.channel = self.term.ssh.invoke_shell(term='xterm') WebTerminalHandler.tasks.append(MyThread(target=self.forward_outbound)) diff --git a/templates/jasset/asset_list.html b/templates/jasset/asset_list.html index fe03cc1a2..eb37d5030 100644 --- a/templates/jasset/asset_list.html +++ b/templates/jasset/asset_list.html @@ -130,6 +130,7 @@ 详情 {% ifnotequal session_role_id 0 %} 编辑 + 连接 删除 {% endifnotequal %} @@ -167,9 +168,46 @@ } ) } - }) + }); + + $('.conn').click(function(evt){ + var url='/jlog/get_role_name/?id' + $(this).attr('value'); + var href = $(this).attr('href'); + var new_url = '/jlog/web_terminal/?id=' + $(this).attr('value') + '&role='; + $.ajax({ + type: 'GET', + url: url, + data: {}, + success: function(data){ + var dataArray = data.split(','); + if (dataArray.length == 1){ + window.open(new_url + data, '播放', 'height=400, width=600, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no'); + } else if (dataArray.length == 0){ + layer.alert('没有授权角色') + } else { + aUrl = ''; + $.each(dataArray, function(index, value){ + aUrl += '' + value + ' ' + }); + layer.alert(aUrl, { + skin: 'layui-layer-molv', + title: '多个角色,请选择一个连接', + closeBtn: 0 + }) + } + + } + }); + return false + }); }); + function windowOpen(aTab){ + var new_url = aTab.href; + window.open(new_url, '播放', 'height=400, width=600, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no'); + return false + } + $(".iframe").on('click', function(){ var asset_id_all = getIDall(); if (asset_id_all == ''){ @@ -206,6 +244,8 @@ }); }); + + $('#asset_del').click(function () { var asset_id_all = getIDall(); if (asset_id_all == ''){ From 4c5055124940d6177a02f49e2b44fb3c808b98b1 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 23 Nov 2015 19:15:52 +0800 Subject: [PATCH 10/20] fix some bug --- jlog/views.py | 4 ++-- run_websocket.py | 7 +++---- templates/jasset/asset_list.html | 12 ++++++------ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/jlog/views.py b/jlog/views.py index 20b7f7c98..82a4891e7 100644 --- a/jlog/views.py +++ b/jlog/views.py @@ -109,8 +109,8 @@ def get_role_name(request): asset = get_object(Asset, id=asset_id) if asset: role = user_have_perm(request.user, asset=asset) - return HttpResponse(','.join(list(role))) - return HttpResponse('dev,sa') + return HttpResponse(','.join([i.name for i in role])) + return HttpResponse('error') @require_role() diff --git a/run_websocket.py b/run_websocket.py index 27420b4ea..58e9e796a 100644 --- a/run_websocket.py +++ b/run_websocket.py @@ -57,15 +57,13 @@ def require_auth(func): uid = session.get_decoded().get('_auth_user_id') user = User.objects.filter(id=uid) asset_id = int(request.get_argument('id', 9999)) - + print asset_id asset = Asset.objects.filter(id=asset_id) if asset: asset = asset[0] request.asset = asset - role = user_have_perm(user, asset) - request.role = role else: - role = '' + request.close() if user: user = user[0] @@ -247,6 +245,7 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): if role.name == role_name: login_role = role break + print login_role if not login_role: print "no role" self.close() diff --git a/templates/jasset/asset_list.html b/templates/jasset/asset_list.html index eb37d5030..d684e7c41 100644 --- a/templates/jasset/asset_list.html +++ b/templates/jasset/asset_list.html @@ -170,8 +170,8 @@ } }); - $('.conn').click(function(evt){ - var url='/jlog/get_role_name/?id' + $(this).attr('value'); + $('.conn').click(function(){ + var url='/jlog/get_role_name/?id=' + $(this).attr('value'); var href = $(this).attr('href'); var new_url = '/jlog/web_terminal/?id=' + $(this).attr('value') + '&role='; $.ajax({ @@ -179,10 +179,11 @@ url: url, data: {}, success: function(data){ + console.log(data); var dataArray = data.split(','); - if (dataArray.length == 1){ + if (dataArray.length == 1 && data != 'error'){ window.open(new_url + data, '播放', 'height=400, width=600, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no'); - } else if (dataArray.length == 0){ + } else if (dataArray.length == '1' && data == 'error'){ layer.alert('没有授权角色') } else { aUrl = ''; @@ -195,7 +196,6 @@ closeBtn: 0 }) } - } }); return false @@ -204,7 +204,7 @@ function windowOpen(aTab){ var new_url = aTab.href; - window.open(new_url, '播放', 'height=400, width=600, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no'); + window.open(new_url, '', 'height=400, width=600, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no'); return false } From a7a030feddda9a24c128d817e94bd4e7441ee392 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 23 Nov 2015 23:07:58 +0800 Subject: [PATCH 11/20] fix bug --- jumpserver/context_processors.py | 8 +- run_websocket.py | 130 +++++++++++++++++-------------- templates/jasset/asset_list.html | 4 +- templates/jlog/log_online.html | 20 ++--- 4 files changed, 81 insertions(+), 81 deletions(-) diff --git a/jumpserver/context_processors.py b/jumpserver/context_processors.py index 35c656c25..e84cc60ec 100644 --- a/jumpserver/context_processors.py +++ b/jumpserver/context_processors.py @@ -5,16 +5,12 @@ from jumpserver.api import * def name_proc(request): user_id = request.user.id - # role_id = request.session.get('role_id') - role_id = {'SU':2,'GA':1,'CU':0}.get(request.user.role,0) - # if role_id == 2: + role_id = {'SU': 2, 'GA': 1, 'CU': 0}.get(request.user.role, 0) + # role_id = 'SU' user_total_num = User.objects.all().count() user_active_num = User.objects.filter().count() host_total_num = Asset.objects.all().count() host_active_num = Asset.objects.filter(is_active=True).count() - # else: - # pass - request.session.set_expiry(3600) info_dic = {'session_user_id': user_id, diff --git a/run_websocket.py b/run_websocket.py index 58e9e796a..6963c1701 100644 --- a/run_websocket.py +++ b/run_websocket.py @@ -7,6 +7,7 @@ import os import sys import os.path import threading +import datetime import urllib import tornado.ioloop @@ -22,7 +23,7 @@ from tornado.options import define, options from pyinotify import WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE, IN_MODIFY, AsyncNotifier import select -from connect import Tty, User, Asset, PermRole +from connect import Tty, User, Asset, PermRole, logger, get_object from connect import TtyLog, Log, Session, user_have_perm try: @@ -35,45 +36,49 @@ define("port", default=3000, help="run on the given port", type=int) define("host", default='0.0.0.0', help="run port on", type=str) -def require_auth(func): - def _deco(request, *args, **kwargs): - if request.get_cookie('sessionid'): - session_key = request.get_cookie('sessionid') - else: - session_key = request.get_secure_cookie('sessionid') +def require_auth(role='user'): + def _deco(func): + def _deco(request, *args, **kwargs): + if request.get_cookie('sessionid'): + session_key = request.get_cookie('sessionid') + else: + session_key = request.get_secure_cookie('sessionid') - print "session: " + session_key + logger.debug('Websocket: session_key: ' + session_key) - if not session_key: - print('Auth Failed') + if session_key: + session = get_object(Session, session_key=session_key) + if session and datetime.datetime.now() > session.expire_date: + user_id = session.get_decoded().get('_auth_user_id') + user = get_object(User, id=user_id) + if user: + logger.debug('Websocket: user [ %s ] request websocket' % user.username) + request.user = user + if role == 'admin': + if user.role in ['SU', 'GA']: + return func(request, *args, **kwargs) + logger.debug('Websocket: user [ %s ] is not admin.' % user.username) + else: + return func(request, *args, **kwargs) request.close() - - session = Session.objects.filter(session_key=session_key) - if not session: - print('Auth Failed') - request.close() - else: - session = session[0] - uid = session.get_decoded().get('_auth_user_id') - user = User.objects.filter(id=uid) - asset_id = int(request.get_argument('id', 9999)) - print asset_id - asset = Asset.objects.filter(id=asset_id) - if asset: - asset = asset[0] - request.asset = asset - else: - request.close() - - if user: - user = user[0] - request.user = user - - else: - print("No session user.") - request.close() - - return func(request, *args, **kwargs) + logger.warning('Websocket: Request auth failed.') + # asset_id = int(request.get_argument('id', 9999)) + # print asset_id + # asset = Asset.objects.filter(id=asset_id) + # if asset: + # asset = asset[0] + # request.asset = asset + # else: + # request.close() + # + # if user: + # user = user[0] + # request.user = user + # + # else: + # print("No session user.") + # request.close() + return _deco return _deco @@ -109,10 +114,10 @@ def file_monitor(path='.', client=None): notifier = AsyncNotifier(wm, EventHandler(client)) wm.add_watch(path, mask, auto_add=True, rec=True) if not os.path.isfile(path): - print "You should monitor a file" + logger.debug("File %s does not exist." % path) sys.exit(3) else: - print "now starting monitor %s." % path + logger.debug("Now starting monitor file %s." % path) global f f = open(path, 'r') st_size = os.stat(path)[6] @@ -158,7 +163,7 @@ class MonitorHandler(tornado.websocket.WebSocketHandler): def check_origin(self, origin): return True - @require_auth + @require_auth('admin') def open(self): # 获取监控的path self.file_path = self.get_argument('file_path', '') @@ -180,7 +185,8 @@ class MonitorHandler(tornado.websocket.WebSocketHandler): MonitorHandler.clients.remove(self) MonitorHandler.threads.remove(MonitorHandler.threads[client_index]) - print len(MonitorHandler.threads), len(MonitorHandler.clients) + logger.debug("Websocket: Monitor client num: %s, thread num: %s" % (len(MonitorHandler.clients), + len(MonitorHandler.threads))) def on_message(self, message): # 监控日志,发生变动发向客户端 @@ -190,10 +196,13 @@ class MonitorHandler(tornado.websocket.WebSocketHandler): # 客户端主动关闭 # self.close() - print "Close websocket." - client_index = MonitorHandler.clients.index(self) - MonitorHandler.clients.remove(self) - MonitorHandler.threads.remove(MonitorHandler.threads[client_index]) + logger.debug("Websocket: Monitor client close request") + try: + client_index = MonitorHandler.clients.index(self) + MonitorHandler.clients.remove(self) + MonitorHandler.threads.remove(MonitorHandler.threads[client_index]) + except ValueError: + pass class WebTty(Tty): @@ -206,6 +215,7 @@ class WebTty(Tty): class WebTerminalKillHandler(tornado.web.RequestHandler): + @require_auth('admin') def get(self): ws_id = self.get_argument('id') Log.objects.filter(id=ws_id).update(is_finished=True) @@ -228,7 +238,6 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): self.log_time_f = None self.log = None self.id = 0 - self.asset = None self.user = None super(WebTerminalHandler, self).__init__(*args, **kwargs) @@ -237,19 +246,22 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): @require_auth def open(self): - print self.user, self.asset - role_name = self.get_argument('role', 'root') - roles = user_have_perm(self.user, self.asset) - login_role = '' - for role in roles: - if role.name == role_name: - login_role = role - break - print login_role - if not login_role: - print "no role" - self.close() - return + role_name = self.get_argument('role', 'sb') + asset_id = self.get_argument('id', 9999) + asset = get_object(Asset, id=asset_id) + if asset: + roles = user_have_perm(self.user, asset) + login_role = '' + for role in roles: + if role.name == role_name: + login_role = role + break + if not login_role: + logger.warning('Websocket: Not that Role %s for Host: %s User: %s ' % (role_name, asset.name, + self.user.username)) + self.close() + return + logger.debug('Websocket: request web terminal Host: %s User: %s Role: %s' % ()) # Todo: 判断 self.term = WebTty(self.user, self.asset, login_role) self.term.get_connection() diff --git a/templates/jasset/asset_list.html b/templates/jasset/asset_list.html index d684e7c41..e6a12567d 100644 --- a/templates/jasset/asset_list.html +++ b/templates/jasset/asset_list.html @@ -179,10 +179,10 @@ url: url, data: {}, success: function(data){ - console.log(data); var dataArray = data.split(','); if (dataArray.length == 1 && data != 'error'){ - window.open(new_url + data, '播放', 'height=400, width=600, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no'); + console.log('one'); + window.open(new_url + data, '', 'height=400, width=600, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no'); } else if (dataArray.length == '1' && data == 'error'){ layer.alert('没有授权角色') } else { diff --git a/templates/jlog/log_online.html b/templates/jlog/log_online.html index 96d8a9d07..42ea11a38 100644 --- a/templates/jlog/log_online.html +++ b/templates/jlog/log_online.html @@ -79,11 +79,9 @@ 用户名 登录主机 来源IP - {% ifnotequal session_role_id 0 %} - 统计命令 - 实时监控 - 阻断 - {% endifnotequal %} + 统计命令 + 实时监控 + 阻断 登录时间 @@ -94,11 +92,9 @@ {{ post.user }} {{ post.host }} {{ post.remote_ip }} - {% ifnotequal session_role_id 0 %} - 命令统计 - 监控 - - {% endifnotequal %} + 命令统计 + 监控 + {{ post.start_time|date:"Y-m-d H:i:s" }} {% endfor %} @@ -188,10 +184,6 @@ }}); return false; }); - - $('#test_connect').click(function(){ - window.open('/jlog/web_terminal/?asset_name="hello', '播放', 'height=400, width=600, top=89px, left=99px,toolbar=no,menubar=no,scrollbars=auto,resizeable=no,location=no,status=no'); - }); }); {# function log_search(){#} From 34031bfd6b21e4883bb3ef7291a1fcd76432b0ae Mon Sep 17 00:00:00 2001 From: halcyon <864072399@qq.com> Date: Mon, 23 Nov 2015 23:55:19 +0800 Subject: [PATCH 12/20] fix bugs --- jasset/models.py | 2 +- jasset/views.py | 12 +++-- .../excels/cmdb_excel_2015_11_20_00_04.xlsx | Bin 0 -> 6125 bytes templates/jasset/asset_add.html | 46 +++++++++++++----- templates/jasset/asset_edit.html | 2 +- templates/jasset/error.html | 2 +- 6 files changed, 43 insertions(+), 21 deletions(-) create mode 100644 static/files/excels/cmdb_excel_2015_11_20_00_04.xlsx diff --git a/jasset/models.py b/jasset/models.py index 4f0ce5107..c6cbe4cb5 100644 --- a/jasset/models.py +++ b/jasset/models.py @@ -57,7 +57,7 @@ class Asset(models.Model): """ asset modle """ - ip = models.GenericIPAddressField(blank=True, null=True, verbose_name=u"主机IP") + ip = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"主机IP") other_ip = models.CharField(max_length=255, blank=True, null=True, verbose_name=u"其他IP") hostname = models.CharField(unique=True, max_length=128, verbose_name=u"主机名") port = models.IntegerField(blank=True, null=True, verbose_name=u"端口号") diff --git a/jasset/views.py b/jasset/views.py index 54bc576a7..17f5a8468 100644 --- a/jasset/views.py +++ b/jasset/views.py @@ -211,20 +211,21 @@ def asset_edit(request): password = request.POST.get('password', '') is_active = True if request.POST.get('is_active') == '1' else False use_default_auth = request.POST.get('use_default_auth', '') - try: asset_test = get_object(Asset, hostname=hostname) if asset_test and asset_id != unicode(asset_test.id): - error = u'该主机名 %s 已存在!' % hostname - raise ServerError(error) + emg = u'该主机名 %s 已存在!' % hostname + raise ServerError(emg) except ServerError: pass else: if af_post.is_valid(): + print 'hehe', af_post af_save = af_post.save(commit=False) if use_default_auth: af_save.username = '' af_save.password = '' + af_save.port = '' else: if password_old != password: password_encode = CRYPTOR.encrypt(password) @@ -237,9 +238,10 @@ def asset_edit(request): info = asset_diff(af_post.__dict__.get('initial'), request.POST) db_asset_alert(asset, username, info) - msg = u'主机 %s 修改成功' % ip + smg = u'主机 %s 修改成功' % ip else: emg = u'主机 %s 修改失败' % ip + return my_render('jasset/error.html', locals(), request) return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id) return my_render('jasset/asset_edit.html', locals(), request) @@ -414,7 +416,7 @@ def asset_update(request): if not asset: return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id) else: - asset_ansible_update(asset_list, name) + asset_ansible_update([asset], name) return HttpResponseRedirect('/jasset/asset_detail/?id=%s' % asset_id) diff --git a/static/files/excels/cmdb_excel_2015_11_20_00_04.xlsx b/static/files/excels/cmdb_excel_2015_11_20_00_04.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..05fc5eefcdcf615a97670bbb3e883e1f28f9b3e5 GIT binary patch literal 6125 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 Ufk;UJ0Bq#@1u{2uAiwVZ51tE?YybcN literal 0 HcmV?d00001 diff --git a/templates/jasset/asset_add.html b/templates/jasset/asset_add.html index 35903a469..807dcd130 100644 --- a/templates/jasset/asset_add.html +++ b/templates/jasset/asset_add.html @@ -55,7 +55,7 @@
    @@ -142,26 +142,46 @@ rules: { check_ip: [/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/, 'ip地址不正确'], check_port: [/^\d{1,5}$/, '端口号不正确'], + use_default_auth: function() { + var str1 = $("#id_use_default_auth").is(":checked"); + if (str1 == true){ + var decide = false; + } else { + var decide = true; + } + return decide} }, fields: { -{# "ip": {#} -{# rule: "required;check_ip",#} -{# tip: "输入IP",#} -{# ok: "",#} -{# msg: {required: "必须填写!"}#} -{# },#} + "ip": { + rule: "check_ip;", + tip: "输入IP", + ok: "", + msg: {required: "必须填写!"} + }, "hostname": { rule: "required", tip: "填写主机名", ok: "", msg: {required: "必须填写!"} }, -{# "port": {#} -{# rule: "required;check_port",#} -{# tip: "输入端口号",#} -{# ok: "",#} -{# msg: {required: "必须填写!"}#} -{# }#} + "port": { + rule: "required(use_default_auth)", + tip: "输入端口号", + ok: "", + msg: {required: "必须填写!"} + }, + "username": { + rule: "required(use_default_auth)", + tip: "输入用户名", + ok: "", + msg: {required: "必须填写!"} + }, + "password": { + rule: "required(use_default_auth)", + tip: "输入密码", + ok: "", + msg: {required: "必须填写!"} + } }, valid: function(form) { form.submit(); diff --git a/templates/jasset/asset_edit.html b/templates/jasset/asset_edit.html index ff9552d4a..1ec1b8ef2 100644 --- a/templates/jasset/asset_edit.html +++ b/templates/jasset/asset_edit.html @@ -55,7 +55,7 @@
    diff --git a/templates/jasset/error.html b/templates/jasset/error.html index 4fa214245..3ad1bf040 100644 --- a/templates/jasset/error.html +++ b/templates/jasset/error.html @@ -1,4 +1,4 @@ -{% for field in af %} +{% for field in af_form %}
    {{ field.errors }}
    {{ field.label_tag }}: {{ field }} {% endfor %} From 17ccac92ee927d05883366afbf768a52c29a5c53 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 24 Nov 2015 11:01:54 +0800 Subject: [PATCH 13/20] =?UTF-8?q?fix=20=E5=8A=A0=E5=AF=86bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jlog/views.py | 6 ++++-- jumpserver/api.py | 2 +- run_websocket.py | 10 +++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/jlog/views.py b/jlog/views.py index 82a4891e7..472f2c3b7 100644 --- a/jlog/views.py +++ b/jlog/views.py @@ -104,6 +104,7 @@ def log_record(request): return HttpResponse('无日志记录!') +@require_role('user') def get_role_name(request): asset_id = request.GET.get('id', 9999) asset = get_object(Asset, id=asset_id) @@ -113,9 +114,10 @@ def get_role_name(request): return HttpResponse('error') -@require_role() +@require_role('user') def web_terminal(request): asset_id = request.GET.get('id') - web_terminal_uri = 'ws://%s/terminal?id=%s&role=dev' % (WEB_SOCKET_HOST, asset_id) + role_name = request.GET.get('role') + web_terminal_uri = 'ws://%s/terminal?id=%s&role=%s' % (WEB_SOCKET_HOST, asset_id, role_name) return render_to_response('jlog/web_terminal.html', locals()) diff --git a/jumpserver/api.py b/jumpserver/api.py index cbf7eebc8..7e2a0d0ef 100644 --- a/jumpserver/api.py +++ b/jumpserver/api.py @@ -59,7 +59,7 @@ def get_asset_info(asset): else: info['port'] = asset.port info['username'] = asset.username - info['password'] = asset.password + info['password'] = CRYPTOR.decrypt(asset.password) return info diff --git a/run_websocket.py b/run_websocket.py index 6963c1701..02b132f2d 100644 --- a/run_websocket.py +++ b/run_websocket.py @@ -257,12 +257,16 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): login_role = role break if not login_role: - logger.warning('Websocket: Not that Role %s for Host: %s User: %s ' % (role_name, asset.name, + logger.warning('Websocket: Not that Role %s for Host: %s User: %s ' % (role_name, asset.hostname, self.user.username)) self.close() return - logger.debug('Websocket: request web terminal Host: %s User: %s Role: %s' % ()) - # Todo: 判断 + else: + logger.warning('Websocket: No that Host: %s User: %s ' % (asset_id, self.user.username)) + self.close() + return + logger.debug('Websocket: request web terminal Host: %s User: %s Role: %s' % (asset.hostname, self.user.username, + login_role.name)) self.term = WebTty(self.user, self.asset, login_role) self.term.get_connection() self.term.channel = self.term.ssh.invoke_shell(term='xterm') From 99439be04fac5e8fef8023fe221cefaa2220ab18 Mon Sep 17 00:00:00 2001 From: wangyong <864072399@qq.com> Date: Tue, 24 Nov 2015 11:20:01 +0800 Subject: [PATCH 14/20] add update all button --- jasset/views.py | 22 ++++++++++-------- templates/jasset/asset_edit.html | 39 ++++++++++++++++++++++---------- templates/jasset/asset_list.html | 18 +++++++++++++++ 3 files changed, 58 insertions(+), 21 deletions(-) diff --git a/jasset/views.py b/jasset/views.py index 17f5a8468..38a7d2a3a 100644 --- a/jasset/views.py +++ b/jasset/views.py @@ -130,6 +130,7 @@ def asset_add(request): af = AssetForm() if request.method == 'POST': af_post = AssetForm(request.POST) + print af_post ip = request.POST.get('ip', '') hostname = request.POST.get('hostname', '') is_active = True if request.POST.get('is_active') == '1' else False @@ -220,12 +221,11 @@ def asset_edit(request): pass else: if af_post.is_valid(): - print 'hehe', af_post af_save = af_post.save(commit=False) if use_default_auth: af_save.username = '' af_save.password = '' - af_save.port = '' + af_save.port = None else: if password_old != password: password_encode = CRYPTOR.encrypt(password) @@ -423,14 +423,18 @@ def asset_update(request): @require_role('admin') def asset_update_batch(request): if request.method == 'POST': - asset_list = [] + arg = request.GET.get('arg', '') name = unicode(request.user.username) + ' - ' + u'自动更新' - asset_id_all = unicode(request.POST.get('asset_id_all', '')) - asset_id_all = asset_id_all.split(',') - for asset_id in asset_id_all: - asset = get_object(Asset, id=asset_id) - if asset: - asset_list.append(asset) + if arg == 'all': + asset_list = Asset.objects.all() + else: + asset_list = [] + asset_id_all = unicode(request.POST.get('asset_id_all', '')) + asset_id_all = asset_id_all.split(',') + for asset_id in asset_id_all: + asset = get_object(Asset, id=asset_id) + if asset: + asset_list.append(asset) asset_ansible_update(asset_list, name) return HttpResponse(u'批量更新成功!') return HttpResponse(u'批量更新成功!') diff --git a/templates/jasset/asset_edit.html b/templates/jasset/asset_edit.html index 1ec1b8ef2..a3f9bd516 100644 --- a/templates/jasset/asset_edit.html +++ b/templates/jasset/asset_edit.html @@ -186,12 +186,20 @@ $('label[for="' + field + '"]').parent().addClass("required"); }); - $('#assetForm').validator({ + $('#assetForm').validator({ timely: 2, theme: "yellow_right_effect", rules: { check_ip: [/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/, 'ip地址不正确'], check_port: [/^\d{1,5}$/, '端口号不正确'], + use_default_auth: function() { + var str1 = $("#id_use_default_auth").is(":checked"); + if (str1 == true){ + var decide = false; + } else { + var decide = true; + } + return decide} }, fields: { "hostname": { @@ -200,17 +208,24 @@ ok: "", msg: {required: "必须填写!"} }, -{# "ip": {#} -{# rule: "required;check_ip",#} -{# tip: "输入IP",#} -{# ok: "",#} -{# msg: {required: "必须填写!"}#} -{# },#} -{# "port": {#} -{# rule: "required;check_port",#} -{# tip: "输入端口号",#} -{# ok: "",#} -{# msg: {required: "必须填写!"}#} + "port": { + rule: "required(use_default_auth)", + tip: "输入端口号", + ok: "", + msg: {required: "必须填写!"} + }, + "username": { + rule: "required(use_default_auth)", + tip: "输入用户名", + ok: "", + msg: {required: "必须填写!"} + }, + "password": { + rule: "required(use_default_auth)", + tip: "输入密码", + ok: "", + msg: {required: "必须填写!"} + } }, valid: function(form) { form.submit(); diff --git a/templates/jasset/asset_list.html b/templates/jasset/asset_list.html index fe03cc1a2..2c8291b01 100644 --- a/templates/jasset/asset_list.html +++ b/templates/jasset/asset_list.html @@ -142,6 +142,7 @@ 修改 +
    {% include 'paginator.html' %} @@ -241,6 +242,23 @@ }); }); +{# function update_tips(){#} +{# layer.tips('我是另外一个tips,只不过我长得跟之前那位稍有些不一样。', '吸附元素选择器', {#} +{# tips: [1, '#3595CC'],#} +{# time: 4000#} +{# });#} +{# }#} + + $('#asset_update_all').click(function () { + layer.msg('玩命更新中...', {time: 200000}); + $.ajax({ + type: "post", + url: "/jasset/asset_update_batch/?arg=all", + success: function () { + parent.location.reload(); + } + }); + }); function change_info(){ var args = $("#asset_form").serialize(); From 30fe9f52363257bf4c5fcd64a370f671903d1eb8 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 24 Nov 2015 11:58:42 +0800 Subject: [PATCH 15/20] =?UTF-8?q?fix=20websocket=E6=8E=88=E6=9D=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jperm/perm_api.py | 2 +- run_websocket.py | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/jperm/perm_api.py b/jperm/perm_api.py index 2bd6de632..53bb06591 100644 --- a/jperm/perm_api.py +++ b/jperm/perm_api.py @@ -138,7 +138,7 @@ def user_have_perm(user, asset): if asset in user_assets: return user_perm_all.get('asset').get(asset).get('role') else: - return False + return [] def gen_resource(ob, ex='', perm=None): diff --git a/run_websocket.py b/run_websocket.py index 02b132f2d..d4ce8bb74 100644 --- a/run_websocket.py +++ b/run_websocket.py @@ -38,17 +38,17 @@ define("host", default='0.0.0.0', help="run port on", type=str) def require_auth(role='user'): def _deco(func): - def _deco(request, *args, **kwargs): + def _deco2(request, *args, **kwargs): if request.get_cookie('sessionid'): session_key = request.get_cookie('sessionid') else: session_key = request.get_secure_cookie('sessionid') - logger.debug('Websocket: session_key: ' + session_key) - + logger.debug('Websocket: session_key: %s' % session_key) if session_key: session = get_object(Session, session_key=session_key) - if session and datetime.datetime.now() > session.expire_date: + logger.debug('Websocket: session: %s' % session) + if session and datetime.datetime.now() < session.expire_date: user_id = session.get_decoded().get('_auth_user_id') user = get_object(User, id=user_id) if user: @@ -60,6 +60,8 @@ def require_auth(role='user'): logger.debug('Websocket: user [ %s ] is not admin.' % user.username) else: return func(request, *args, **kwargs) + else: + logger.debug('Websocket: session expired: %s' % session_key) request.close() logger.warning('Websocket: Request auth failed.') # asset_id = int(request.get_argument('id', 9999)) @@ -78,7 +80,7 @@ def require_auth(role='user'): # else: # print("No session user.") # request.close() - return _deco + return _deco2 return _deco @@ -244,13 +246,15 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): def check_origin(self, origin): return True - @require_auth + @require_auth('user') def open(self): + logger.debug('Websocket: Open request') role_name = self.get_argument('role', 'sb') asset_id = self.get_argument('id', 9999) asset = get_object(Asset, id=asset_id) if asset: roles = user_have_perm(self.user, asset) + logger.debug(roles) login_role = '' for role in roles: if role.name == role_name: @@ -267,7 +271,7 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): return logger.debug('Websocket: request web terminal Host: %s User: %s Role: %s' % (asset.hostname, self.user.username, login_role.name)) - self.term = WebTty(self.user, self.asset, login_role) + self.term = WebTty(self.user, asset, login_role) self.term.get_connection() self.term.channel = self.term.ssh.invoke_shell(term='xterm') WebTerminalHandler.tasks.append(MyThread(target=self.forward_outbound)) @@ -302,7 +306,7 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): self.term.channel.send(data['data']) def on_close(self): - print 'On_close' + logger.debug('Websocket: Close request') if self in WebTerminalHandler.clients: WebTerminalHandler.clients.remove(self) try: From 7cbb7718eb1113c2aea84ccea1506da461252055 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 24 Nov 2015 12:03:38 +0800 Subject: [PATCH 16/20] fix bug --- jperm/utils.py | 2 +- templates/jperm/perm_role_add.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jperm/utils.py b/jperm/utils.py index a6b3608ee..8561eb8f7 100644 --- a/jperm/utils.py +++ b/jperm/utils.py @@ -46,7 +46,7 @@ def gen_keys(): """ key_basename = "key-" + uuid4().hex key_path_dir = os.path.join(KEY_DIR, 'role_key', key_basename) - mkdir(key_path_dir, 0755) + mkdir(key_path_dir, mode=0755) key = RSAKey.generate(2048) private_key = os.path.join(key_path_dir, 'id_rsa') public_key = os.path.join(key_path_dir, 'id_rsa.pub') diff --git a/templates/jperm/perm_role_add.html b/templates/jperm/perm_role_add.html index 243452db0..ef0753982 100644 --- a/templates/jperm/perm_role_add.html +++ b/templates/jperm/perm_role_add.html @@ -34,7 +34,7 @@
    {{ msg }}
    {% endif %}
    - +
    From 168157bfe12fbd21ecea5e535f7edd5188a062c1 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 24 Nov 2015 13:31:48 +0800 Subject: [PATCH 17/20] fix --- connect.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/connect.py b/connect.py index f4e21fe7b..c486c0199 100644 --- a/connect.py +++ b/connect.py @@ -21,7 +21,7 @@ if django.get_version() != '1.6': django.setup() from django.contrib.sessions.models import Session from jumpserver.api import ServerError, User, Asset, PermRole, AssetGroup, get_object, mkdir, get_asset_info, get_role -from jumpserver.api import logger, Log, TtyLog, get_role_key +from jumpserver.api import logger, Log, TtyLog, get_role_key, CRYPTOR from jperm.perm_api import gen_resource, get_group_asset_perm, get_group_user_perm, user_have_perm from jumpserver.settings import LOG_DIR from jperm.ansible_api import Command @@ -211,9 +211,16 @@ class Tty(object): 获取需要登陆的主机的信息和映射用户的账号密码 """ asset_info = get_asset_info(self.asset) + role_pass = CRYPTOR.decrypt(self.role.password) + role_key = os.path.join(self.role.key_path, 'id_rsa') self.connect_info = {'user': self.user, 'asset': self.asset, 'ip': asset_info.get('ip'), 'port': int(asset_info.get('port')), 'role_name': self.role.name, - 'role_pass': self.role.password, 'role_key': self.role.key_path} + 'role_pass': role_pass, 'role_key': role_key} + logger.debug("Connect: Host: %s Port: %s User: %s Pass: %s Key: %s" % (asset_info.get('ip'), + asset_info.get('port'), + self.role.name, + role_pass, + role_key)) return self.connect_info def get_connection(self): @@ -237,7 +244,7 @@ class Tty(object): look_for_keys=False) self.ssh = ssh return ssh - except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException: + except (paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException): pass ssh.connect(connect_info.get('ip'), From ec9b00e2554d9f606fde443fbe814bc46ddfa48f Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 24 Nov 2015 13:37:36 +0800 Subject: [PATCH 18/20] fix bug --- connect.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/connect.py b/connect.py index c486c0199..de2e18bdb 100644 --- a/connect.py +++ b/connect.py @@ -211,8 +211,8 @@ class Tty(object): 获取需要登陆的主机的信息和映射用户的账号密码 """ asset_info = get_asset_info(self.asset) + role_key = get_role_key(self.user, self.role) role_pass = CRYPTOR.decrypt(self.role.password) - role_key = os.path.join(self.role.key_path, 'id_rsa') self.connect_info = {'user': self.user, 'asset': self.asset, 'ip': asset_info.get('ip'), 'port': int(asset_info.get('port')), 'role_name': self.role.name, 'role_pass': role_pass, 'role_key': role_key} @@ -234,7 +234,7 @@ class Tty(object): ssh.load_system_host_keys() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: - role_key = get_role_key(self.user, self.role) + role_key = connect_info.get('role_key') if role_key and os.path.isfile(role_key): try: ssh.connect(connect_info.get('ip'), @@ -245,6 +245,7 @@ class Tty(object): self.ssh = ssh return ssh except (paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException): + logger.warning('Use ssh key %s Failed.' % role_key) pass ssh.connect(connect_info.get('ip'), From 1a63d32fe35cfee34ec354bb50d61b63dd3786d0 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 24 Nov 2015 16:31:06 +0800 Subject: [PATCH 19/20] fix bug --- jlog/views.py | 1 + jumpserver/api.py | 5 ++++- run_websocket.py | 19 +++++++------------ templates/jlog/log_online.html | 18 +++--------------- 4 files changed, 15 insertions(+), 28 deletions(-) diff --git a/jlog/views.py b/jlog/views.py index 472f2c3b7..6e319c808 100644 --- a/jlog/views.py +++ b/jlog/views.py @@ -51,6 +51,7 @@ def log_list(request, offset): web_monitor_uri = 'ws://%s/monitor' % WEB_SOCKET_HOST web_kill_uri = 'http://%s/kill' % WEB_SOCKET_HOST + session_id = request.session.session_key return render_to_response('jlog/log_%s.html' % offset, locals(), context_instance=RequestContext(request)) diff --git a/jumpserver/api.py b/jumpserver/api.py index 7e2a0d0ef..b44d5d4e5 100644 --- a/jumpserver/api.py +++ b/jumpserver/api.py @@ -54,7 +54,10 @@ def get_asset_info(asset): if default: info['port'] = default.default_port info['username'] = default.default_user - info['password'] = CRYPTOR.decrypt(default.default_password) + try: + info['password'] = CRYPTOR.decrypt(default.default_password) + except ServerError: + pass info['ssh_key'] = default.default_pri_key_path else: info['port'] = asset.port diff --git a/run_websocket.py b/run_websocket.py index d4ce8bb74..168d50ba9 100644 --- a/run_websocket.py +++ b/run_websocket.py @@ -42,7 +42,7 @@ def require_auth(role='user'): if request.get_cookie('sessionid'): session_key = request.get_cookie('sessionid') else: - session_key = request.get_secure_cookie('sessionid') + session_key = request.get_argument('sessionid', '') logger.debug('Websocket: session_key: %s' % session_key) if session_key: @@ -62,7 +62,10 @@ def require_auth(role='user'): return func(request, *args, **kwargs) else: logger.debug('Websocket: session expired: %s' % session_key) - request.close() + try: + request.close() + except AttributeError: + pass logger.warning('Websocket: Request auth failed.') # asset_id = int(request.get_argument('id', 9999)) # print asset_id @@ -99,14 +102,7 @@ class EventHandler(ProcessEvent): def __init__(self, client=None): self.client = client - def process_IN_CREATE(self, event): - print "Create file:%s." % os.path.join(event.path, event.name) - - def process_IN_DELETE(self, event): - print "Delete file:%s." % os.path.join(event.path, event.name) - def process_IN_MODIFY(self, event): - print "Modify file:%s." % os.path.join(event.path, event.name) self.client.write_message(f.read()) @@ -222,12 +218,11 @@ class WebTerminalKillHandler(tornado.web.RequestHandler): ws_id = self.get_argument('id') Log.objects.filter(id=ws_id).update(is_finished=True) for ws in WebTerminalHandler.clients: - print ws.id if ws.id == int(ws_id): - print "killed" + logger.debug("Kill log id %s" % ws_id) ws.log.save() ws.close() - print len(WebTerminalHandler.clients) + logger.debug('Websocket: web terminal client num: %s' % len(WebTerminalHandler.clients)) class WebTerminalHandler(tornado.websocket.WebSocketHandler): diff --git a/templates/jlog/log_online.html b/templates/jlog/log_online.html index 42ea11a38..562c530a4 100644 --- a/templates/jlog/log_online.html +++ b/templates/jlog/log_online.html @@ -50,7 +50,7 @@
    -
    用户日志详细信息列表
    +
    用户日志详细信息列表
    @@ -186,29 +186,17 @@ }); }); -{# function log_search(){#} -{# $.ajax({#} -{# type: "GET",#} -{# url: "/jlog/search/?env=online",#} -{# data: $("#search_form").serialize(),#} -{# success: function (data) {#} -{# $(".tab-content").html(data);#} -{# }#} -{# });#} -{# }#} - - function cut(num, host){ console.log(host); if (host=='Web'){ var g_url = '{{ web_kill_uri }}' + '?id=' + num; } else { - g_url = "/jlog/log_kill/?id=" + num; + var g_url = "/jlog/log_kill/?id=" + num; } $.ajax({ type: "GET", - url: g_url, + url: g_url+"&sessionid={{ session_id }}", success: window.open("/jlog/log_list/online/", "_self") }); From 0262d94dd343736a3723e0a9f7d408425d37facb Mon Sep 17 00:00:00 2001 From: wangyong <864072399@qq.com> Date: Tue, 24 Nov 2015 19:04:16 +0800 Subject: [PATCH 20/20] fix disk detail bug --- jumpserver.conf | 2 +- jumpserver/templatetags/mytags.py | 6 +++++- templates/jasset/asset_edit.html | 6 +++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/jumpserver.conf b/jumpserver.conf index 6297ab00a..41894e0d9 100644 --- a/jumpserver.conf +++ b/jumpserver.conf @@ -13,7 +13,7 @@ password = mysql234 database = jumpserver [websocket] -web_socket_host = j:3000 +web_socket_host = js:3000 [mail] mail_enable = 1 diff --git a/jumpserver/templatetags/mytags.py b/jumpserver/templatetags/mytags.py index c8f5debde..2759838f2 100644 --- a/jumpserver/templatetags/mytags.py +++ b/jumpserver/templatetags/mytags.py @@ -209,7 +209,11 @@ def str_to_dic(info): """ str to list """ - return ast.literal_eval(info).iteritems() + if '{' in info: + info_dic = ast.literal_eval(info).iteritems() + else: + info_dic = {} + return info_dic @register.filter(name='str_to_code') diff --git a/templates/jasset/asset_edit.html b/templates/jasset/asset_edit.html index a3f9bd516..c22bab6ca 100644 --- a/templates/jasset/asset_edit.html +++ b/templates/jasset/asset_edit.html @@ -96,15 +96,15 @@
    {{ af.memory|bootstrap_horizontal }} +
    + {{ af.disk|bootstrap_horizontal }} +
    {{ af.system_type|bootstrap_horizontal }}
    {{ af.system_version|bootstrap_horizontal }} -
    - {{ af.disk|bootstrap_horizontal }} -
    {{ af.number|bootstrap_horizontal }}