5/9eNddlmZddlmZddlmZmZddlZddlZddlZddl Z ddl Z ddl Z ddl m Z ddlmZddlmZddlmZmZdd lmZ ddlZn #e$rdZYnwxYwdd lmZeZd Zd Zd ZdZGdde Z!Gdde!Z"Gdde!Z#Gdde$Z%Gdde$Z&Gdde Z'Gdde$Z(Gdde$Z)dS))print_function)absolute_import)maprangeN)Optional)uid_max)ProcLve)cpapiClPwd) NotSupported) ve_configiresellerceZdZdS) NameMapErrorN__name__ __module__ __qualname__ py/lveapi.pyrr,DrrceZdZdS)NameMapConfigErrorNrrrrrr0rrrceZdZdS)NameMapNotInitializedNrrrrrr4rrrcJeZdZdZefdZdZdZdZd dZ d Z d d Z d Z dS)NameMapz Container for backend storing resellers_name<=>resellers_id map As backend store use ve.cfg Usage: >>> name_map = NameMap() >>> name_map.link_xml_node() >>> name_map.id_list() [1001] c0||_d|_d|_dSN) _xml_tag_name _xml_node_reseller_id_name_map)self xml_tag_names r__init__zNameMap.__init__Ds)%)"""rcN|D]\}}||kr|cSdSr"load_from_node)r&namename_id_s rget_idzNameMap.get_idJsB--//  JE3}}   rcN|D]\}}||kr|cSdSr"r*)r&r.r-_ids rget_namezNameMap.get_nameOsB--//  JE3czz   rc>d|DS)Ncg|]\}}|Srr).0_r.s r z#NameMap.id_list..Us8883888rr*r&s rid_listzNameMap.id_listTs"88$"5"5"7"78888rNTcb|d|_||dS||_d|_dS)aC Initialize NameMap. If xml_node is none, config will be loaded automatically :param use_cache: Bool whether bypass ve.cfg xml cache :param xml_node: !! DEPRECATED PARAM !! this param is left only for compatibility with our old code N)r$_load_resellers_map_from_ve_cfgr%)r&xml_node use_caches r link_xml_nodezNameMap.link_xml_nodeWsB  !DN  0 0 ; ; ; ; ;&DN)-D & & &rc,t|_||\}}|D]b}|d}t |d}|r'|r%||jvr|j||fc~~dS)zT Fills self._reseller_id_name_map from ve.cfg file :return: r=useridN)listr%_try_get_xml_node getAttributeintappend)r&r=ve_cfgr<el_r,r.s rr;z'NameMap._load_resellers_map_from_ve_cfgis &*VV"11I1FF ? ?C##F++Dc&&t,,--C ? ?4+E E E*113+>>>  FFrc tj|\}}n)#tj$rd|_t dwxYw|||jfS)Nr@z-Error happened while loading data from ve.cfg)r get_xml_configBadVeConfigExceptionr%rgetElementsByTagNamer#)r&r=rHr<s rrDzNameMap._try_get_xml_nodeysy V(7)LLL FHH- V V V)-D &$%TUU U Vx44T5GHHHHs &Ac#PK|j|jtd|jrc|j|jD]C}|d}t |d}|r|r||fVD|jr|jD] \}}||fV dSdS)z? Obtain data from xml node as (name, id_) list NzLName map is not initialized. Use obj.link_xml_node() to get data from configrArB)r$r%rrMr#rErF)r&rIr,r.s rr+zNameMap.load_from_nodes > !d&@&H')Z[[ [ > $~::4;MNN $ $''//#**40011$C$)OOO  % !7  TCi    r)NT)T) rrr__doc__LVP_XML_TAG_NAMEr(r/r2r9r>r;rDr+rrrr r 8s  %5****   999....$ IIII     rr cpeZdZdZdZdZd dZdZdZdZ d Z e d Z e d Z d ZdS)LvpMapzl Container for storing information about lve:lvp mapping In which reseller container stored lve ct|_t|_t|_d|_t |_dSr")r name_mapdict _id_name_map _name_id_map_reseller_id_map_panelr _pwdr8s rr(zLvpMap.__init__s<   FF FF&*#GG rc.||j|<||j|<dSr")rVrW)r&r,r.s r_add_mapzLvpMap._add_maps"!%#"%$rNcp |j|jS#tj$r|cYSwxYwr")rYget_pw_by_namepw_uidr NoSuchUserException)r&r,defaults rr^z LvpMap.pw_uidsG 9++D118 8(   NNN s !55c||}||S|jtj|_|j|Sr")r^rXr get_reseller_id_pairsget)r&ruids r_get_panel_reseller_idzLvpMap._get_panel_reseller_idsPkk(## ?J  & .*/*E*G*GD '*..x888rc|j|p|j|}||S ||}n#t $rd}YnwxYw|||||S)z Convert reseller name to an LVE id. It supports resellers without a system account (for Plesk compatibility). N)rTr/rWrcrer r[)r&r,rds rget_reseller_idzLvpMap.get_reseller_ids m""4((GD,=,A,A$,G,G ?J --d33CC   CCC  ? MM$ $ $ $ sA AAc*|j|p|j|}||S t j|j}tj|r| ||nd}n#t$rd}YnwxYw|S)z Convert reseller id to reseller name It support resellers without system account (for Plesk compatibilyty) N) rTr2rVrcpwdgetpwuidpw_namer is_resellerr[KeyError)r&r.r,s rget_reseller_namezLvpMap.get_reseller_names }%%c**Hd.?.C.CC.H.H  K <$$,D &&  dC((((   DDD  sAB BBc#Kttj}i}|D]M} ||||<#t$r%t jt jd|zYJwxYwtjdD][\}}||}|#t jt jd|z?| |d}||fV\dS)z This method loops over all user:reseller pairs in control panel and returns appropriate lve_id:lvp_id pairs. THIS METHOD WON'T CHECK IF 'RESELLER LIMITS' IS ENABLED IN ve.cfg zIReseller %s still exists in control panel, but absent in /etc/passwd file)cploginr)keylsNEuser %s still exists in control panel, but absent in /etc/passwd filer) setr resellersrgr syslog LOG_WARNINGcpinfor^rc)r&rt reseller_uidsrrplve_idlvp_ids r lve_lvp_pairszLvpMap.lve_lvp_pairssJ ))**  ! U UH U*.*>*>x*H*H h'' U U U &)IKS)TUUUUU U"'4K!L!L!L ! ! GX[[))F ~ &)IKR)STTT"&&x33F&.  ! !sA,A21A2c#>KtjD]}|VdSr")r rt) reseller_names rrtzLvpMap.resellerss6"_..  M      rct}tj|}|D]c} tj|j}||2#t$r%tjtj d|zY`wxYw|S)z: Obtain from control panel resellers uids rr) rCr reseller_usersrigetpwnamr^rGrmrurv)r,uidsrrAr.s rrxzLvpMap.reseller_uidss vv-d33" Q QD Ql4((/ C     Q Q Q &)IKO)PQQQQQ Q s.A,BBcV||}||Sr")rnrx)r&rzr}s rlvp_lve_id_listzLvpMap.lvp_lve_id_lists)..v66 !!-000rr")rrrrOr(r[r^rergrnr{ staticmethodrtrxrrrrrRrRs&&& 9 9 9"&!!!:  \ \ 11111rrRceZdZdS) PyLveErrorNrrrrrrrrrceZdZdZedZdZdZdZe dddfd Z d Z d Z d Z eefd ZejdZdS)PyLvezA Wrapper for generate traceback with pretty descriptions cZt|to|tj ko|dkS)Nr) isinstancerFerrnoENOSYS)codes r_code_is_errorzPyLve._code_is_errors)$$$L%,)>L419Lrct|jjrDdfdt D}d|}nt }|S)N, c g|];}|dd|t|.!si.E.E.EYZrsr~r~@CsDsD.EgnnQQR@S@S.T.T.E.E.Erz)r_pylveliblve_settingsjoindirrstr)r&rliblve_settings_attr arg_var_strs ` r _arg_to_strzPyLve._arg_to_strs gt{: ; ; '#'99.E.E.E.E^abi^j^j.E.E.E$F$F 7>>?STTKKg,,Krc |dj}|dj}||i|}|}|r=jr6t jj||i|}|}t||j |j d ttj|fd|Dz}jdkrt#jjdi|jdkrj|s|r|jdi|} t-| |S) Nerr_msg ignore_errorrchg|].\}}d||/S)r)rr)r5kvr&s rr7z&PyLve._wrapped_fun..4s<+n+n+nW[WXZ[GNN1d>N>Nq>Q>Q,R,R+n+n+nr)rfun_namemoduleargs_rr)popdefault_msg_templaterr_retrytimesleep _retry_timerUrrrrCrritemsdebugprintdebug_msg_templater traceback print_stackr) r&callargskwargs msg_templaterris_error format_argsmsgs ` r _wrapped_funzPyLve._wrapped_fun'szz)T-FGG zz.$2CDD tT$V$$&&t,,  1  1 Jt' ( ( (4(((D**400H$(M"&/!%4D4Dd0K0K+L+L+n+n+n+n_e_k_k_m_m+n+n+n,o"p"pqqq :?? 0$)0??;?? @ @ @ :?? N & & ( ( ( " "%,%44 44CS// ! rcfd}|S)Nc&jg|Ri|Sr")r)rrrr&s rfunzPyLve._wrap_code..fun?s&$4$T;D;;;F;; ;rr)r&rrs`` r _wrap_codezPyLve._wrap_code>s' < < < < < < rTg?rc0||_|jdkrtd|_d|_d|_d|_||_||_t|_ ||_ |j |_ |jj |_ ||jj|_|jj|_||jj|_||jj|_|jj|_||jj|_||jj|_||jj|_||jj|_||jj|_t3|dr||jj|_||jj|_||jj|_||jj|_||j|_dSdS)Nrrz/Error code {code}; {module}.{fun_name}({args_})zBDEBUG [lvectl]: call {module}.{fun_name}({args_}) with code {code}Flve_lvp_create)r __import__rrrrrrr _procrlve_get_api_version api_version initializer lve_startr lve_create lve_destroylve_infolve_set_default lve_setup lve_enter_pidlve_enter_pid_flags lve_leave_pidhasattrrlve_lvp_destroy lve_lvp_map lve_lvp_move lve_lvp_setup)r&pylveretry retry_tymers rr(zPyLve.__init__Cs :??' 44DN$U!"f!  YY %;::<<+0)>??#{://$+*@AA??4;+BCC , #t{/JKK)>??!__T[-FGG#'??4;3R#S#S !__T[-FGG 5* + + E"&//$+2L"M"MD #'??4;3N#O#OD #t{/FGGD  $ 0H I ID "&1C!D!DD    E Erc,t|jdS)zB Check in pylve binding reseller limits supported r)rrr8s rresellers_supportedzPyLve.resellers_supporteddst{$4555rcT ||dS#t$rYdSwxYw)zD Check if lve exists in kernel :rtype: bool TF)rOSError)r&rys r lve_existszPyLve.lve_existsjs@   MM& ! ! !4   55 s  ''c|dkr|j||Si}|j|D]} ||}|||<|j|jkrJ||}t |j|j|_|||x#t$rYwxYw| |jj}|||d}|j|D]L}||vr||||#||||M|S)a Wrapper for lve_lvp_setup. When reseller's limits changed, we should iterate over his user's limits and set them again; This behaviour is needed cause kernel does not update users limits after changing reseller's one Adjust parameters for top level container. :param int lvp_id: top level container ID, 0 by default; :param settings: liblve_settings instance. :return: 0 or errno value rTr) rrr lve_id_listrls_cpuminrrr) r&rzsettingsreal_lve_settingsry real_settings temp_settings_lve_lvp_setupresults rrzPyLve.lve_lvp_setupws~" Q;;;,,VX>> >!# *0088   $(MM&$9$9M0=%f-$+ho==(, f(=(= /2=3G/Y/Y ,v}===D "__T[-FGGN#^FH4HHHF*0088 B B...NN6+>c#XK||jc|_} dV||_dS#||_wxYwr"r)r&rsaved_ignore_errors rcontext_ignore_errorzPyLve.context_ignore_errorsJ0O-- 3 EEE 2D    2D  2 2 2 2s )N)rrrrOrrrrrrr(rrrUID_MAX MAX_LVE_IDr contextlibcontextmanagerrrrrrrsMM\M. #$3aEEEEB666   555n*1z V V V V33333rrcFeZdZd dZdZdZdZdZdZdZ d Z d Z dS) LveNc|p t|_|p t|_|p t |_dSr")r procrpyrRr)r&rrrs rr(z Lve.__init__s4%GII -?&((rc#Kt|jj}|jD]\}}||vr||fV|dfVdS)a5 Obtain {lve id}:{lvp id} pairs iterator based on ve.cfg config (detect enabled resellers containers) This method (unlike LvpMap.lve_lvp_pairs) will check if reseller is enabled in ve.cfg and return lvp_id=0 for users of reseller with disabled reseller limits rN)rsrrTr9r{)r&enabled_lvp_idryrzs rlve_id_lvp_id_pairszLve.lve_id_lvp_id_pairss~TX.668899"h4466  NFF''fn$$$$ai   rcN|D]\}}||kr|cSdS)z\ Obtain lvp id based on ve.cfg config (detect enabled resellers containers) r)r)r&rylve_id_lvp_id_s rlve2lvpz Lve.lve2lvpsB!% 8 8 : :   GW  !qrctj|jr.|j|d}nd}|jj|g|Ri||dkrC tj ||j ||dS#t$rYdSwxYwdS)zH safe destroy lve container with preserving lvp mapping rN) ospathexistsr proc_lve_maprrcrrrirjrrm)r&ryrrrzs rrzLve.lve_destroys 7>>$)0022 3 3 Y]]__((33FFFF4T444V444 Q;;  V$$$##FF33333     ;s/B55 CCcJ|j}|D]t\}}||d|krU|j|s|j||j|||||<udS)z4 Load lve_id:lvp_id map to kmod-lve r)rzN)rrrrc exist_lvprrr)r& proc_map_dictryrzs r _sync_mapz Lve._sync_maps   #6688 / /NFF  ++v55y**&*993G**6222$$VV444(. f%  / /rcR |dS#t$rYdSwxYw)zZ wrapped _sync_map function for prevent error if some cpapi not supported N)rr r8s rsync_mapz Lve.sync_maps?  NN         DD s  &&cL tjS#t$rYdSwxYw)z^ Check if current panel supported for reseller's limits; :rtype: bool F)r is_reseller_limits_supportedr r8s ris_panel_supportedzLve.is_panel_supporteds8  577 7   55 s  ##ct|j|j|fS)zo Check present all needed (kmod-lve, liblve, /proc/lve, panel) for manipulate resellers limits )allrrrr r8s rreseller_limit_supportedzLve.reseller_limit_supportedsKDG//11I1133++--/00 0rct|j|jfS)zh Check present all needed (kmod-lve, liblve, /proc/lve) for manipulate resellers limits )rrrrr8s ris_lve10z Lve.is_lve10!s3DG//11493P3P3R3RSTTTr)NNN) rrrr(rrrrr r rrrrrrrs####     ///$000UUUUUrr)* __future__rrbuiltinsrrrrrrurritypingrclcommon.clfuncrclcommon.clprocr clcommonr r clcommon.cpapi.cpapiexceptionsr r ImportError clveconfigr rrrP LVE_NO_UBCLVE_NO_MAXENTER Exceptionrrrobjectr rRrrrrrrr s&%%%%%&&&&&& ############!!!!!!!!777777LLLL EEE!  '))         9                L   [ [ [ [ [ f[ [ [ |z1z1z1z1z1Vz1z1z1z        k3k3k3k3k3Fk3k3k3\`U`U`U`U`U&`U`U`U`U`UsAAA