§ ½@¾j°<ãó²—dZddlZddlZddlZddlmZmZddlmZ ddl Z n #e $rdZ YnwxYwe¦«Z dZ Gd„de¦«ZGd„d ¦«ZdS) u£pylve C-binding wrapper and related types. This module wraps the pylve C extension (PyLve, PyLveError) and lives outside lveapi deliberately: websiteisolation.* is imported by lveapi at the top level, so any websiteisolation sub-module that needs PyLve or PyLveError must not import from lveapi — that would form a cycle. Placing these types here breaks the cycle; lveapi re-exports them for backward compatibility. éN)ÚProcLveÚ LIMIT_LVP_ID)Úuid_maxiþÿÿcó—eZdZdS)Ú PyLveErrorN)Ú__name__Ú __module__Ú __qualname__©óúpy/lve_utils/pylve_wrapper.pyrr#s€€€€€Ø€Dr rcó°—eZdZdZed„¦«Zd„Zd„Zd„Ze dddfd „Z d „Z d „Z d „Z d „Zd„Zd„Zed„¦«Zeefd„Zejd„¦«ZdS)ÚPyLvezA Wrapper for generate traceback with pretty descriptions cóZ—t|t¦«o|tj ko|dkS)Nr)Ú isinstanceÚintÚerrnoÚENOSYS)Úcodes r Ú_code_is_errorzPyLve._code_is_error+s)€å˜$¥Ñ$Ô$ÐL¨µ%´,°Ò)>ÐLÀ4È1Â9ÐLr cóć—t‰|jj¦«r5d ˆfd„t ‰¦«D¦«¦«}d|›d�}nt ‰¦«}|S)Nú, cód•—g|],}| d¦«°|›dt‰|¦«›�‘Œ-S)Ú_ú=)Ú startswithÚgetattr)Ú.0ÚattrÚarg_vars €r ú z%PyLve._arg_to_str..2sFø€ÐiÐiÐi¸ÐTX×TcÒTcÐdgÑThÔThÐi�DÐ3Ð3�7 7¨DÑ1Ô1Ð3Ð3ÐiÐiÐir z)rÚ_pylveÚliblve_settingsÚjoinÚdirÚstr)Úselfr Úliblve_settings_attrÚ arg_var_strs ` r Ú _arg_to_strzPyLve._arg_to_str/srø€Ý �g˜tœ{Ô:Ñ ;Ô ;ð 'Ø#'§9¢9ØiÐiÐiÐiÅÀGÁ Ä ÐiÑiÔiñ$ô$Ð ðMÐ5IÐLÐLÐLˆKˆKå˜g™,œ,ˆKØÐr c óÒ‡—| d‰j¦«}| d‰j¦«}||i|¤Ž}‰ |¦«}|r=‰jr6t j‰j¦«||i|¤Ž}‰ |¦«}||j|j d  tt‰j |¦«¦«ˆfd„| ¦«D¦«z¦«dœ}‰jdkrt!‰jjdi|¤Ž¦«‰jdkr‰j ¦«|s|r|jdi|¤Ž} t+| ¦«‚|S) NÚerr_msgÚ ignore_errorrcóJ•—g|]\}}|›d‰ |¦«›�‘Œ S)r)r+)rÚkÚvr(s €r r!z&PyLve._wrapped_fun..Hs9ø€ÐXÐXÐXÁÀÀA 1Ð <Ð < t×'7Ò'7¸Ñ':Ô':Ð <Ð <ÐXÐXÐXr )rÚfun_nameÚmoduleÚargs_éér )ÚpopÚdefault_msg_templater.rÚ_retryÚtimeÚsleepÚ _retry_timerr r%ÚlistÚmapr+ÚitemsÚdebugÚprintÚdebug_msg_templateÚformatÚ tracebackÚ print_stackr) r(ÚcallÚargsÚkwargsÚ msg_templater.rÚis_errorÚ format_argsÚmsgs ` r Ú _wrapped_funzPyLve._wrapped_fun9s”ø€Ø—z’z )¨TÔ-FÑGÔGˆ Ø—z’z .°$Ô2CÑDÔDˆ ؈t�TÐ$˜VÐ$Ð$ˆØ×&Ò& tÑ,Ô,ˆØ ð 1˜œ ð 1Ý ŒJ�tÔ'Ñ (Ô (Ð (Ø�4˜Ð( Ð(Ð(ˆDØ×*Ò*¨4Ñ0Ô0ˆHðØœ Ø”oØ—Y’Y�t¥C¨Ô(8¸$Ñ$?Ô$?Ñ@Ô@ØXÐXÐXÐXÈÏÊÉÌÐXÑXÔXñ YñZôZð  ð ˆ ð Œ:˜Š?ˆ?Ý Ð0�$Ô)Ô0Ð?Ð?°;Ð?Ð?Ñ @Ô @Ð @Ø Œ:˜Š?ˆ?Ø ŒN× &Ò &Ñ (Ô (Ð (Øð " ð "Ø%�,Ô%Ð4Ð4¨ Ð4Ð4ˆCݘS‘/”/Ð !؈ r c󇇗ˆˆfd„}|S)Ncó&•—‰j‰g|¢Ri|¤ŽS©N)rM)rGrHrFr(s €€r ÚfunzPyLve._wrap_code..funTs&ø€Ø$�4Ô$ TÐ;¨DÐ;Ð;Ð;°FÐ;Ð;Ð ;r r )r(rFrQs`` r Ú _wrap_codezPyLve._wrap_codeSs'øø€ð <ð <ð <ð <ð <ð <àˆ r Tgš™™™™™¹?rcó˜—||_|jdkrtd¦«|_d|_d|_d|_||_||_t¦«|_ ||_ |j  ¦«|_ |jj |_ | |jj¦«|_|jj|_| |jj¦«|_| |jj¦«|_|jj|_| |jj¦«|_| |jj¦«|_| |jj¦«|_| |jj¦«|_| |jj¦«|_t3|d¦«r¯| |jj¦«|_| |jj¦«|_| |jj¦«|_| |jj¦«|_| |j¦«|_t3|d¦«r&| |jj¦«|_dSdS)Nr6rDz/Error code {code}; {module}.{fun_name}({args_})zBDEBUG [lvectl]: call {module}.{fun_name}({args_}) with code {code}FÚlve_lvp_createÚlve_lvp_create2) r@Ú __import__rDr8rBr.r#r9rÚ_procr<Úlve_get_api_versionÚ api_versionÚ initializerRÚ lve_startr$Ú lve_createÚ lve_destroyÚlve_infoÚlve_set_defaultÚ lve_setupÚ lve_enter_pidÚlve_enter_pid_flagsÚ lve_leave_pidÚhasattrrTÚlve_lvp_destroyÚ lve_lvp_mapÚ lve_lvp_moveÚ lve_lvp_setuprU)r(ÚpylveÚretryÚ retry_tymer@s r Ú__init__zPyLve.__init__Xs,€ØˆŒ Ø Œ:˜Š?ˆ?Ý'¨ Ñ4Ô4ˆDŒNØ$UˆÔ!Ø"fˆÔØ!ˆÔ؈Œ ؈Œ Ý‘Y”YˆŒ Ø%ˆÔØœ;×:Ò:Ñ<Ô<ˆÔàœ+Ô0ˆŒØŸš¨¬Ô)>Ñ?Ô?ˆŒØ#œ{Ô:ˆÔØŸ/š/¨$¬+Ô*@ÑAÔAˆŒØŸ?š?¨4¬;Ô+BÑCÔCˆÔØœ Ô,ˆŒ Ø#Ÿš¨t¬{Ô/JÑKÔKˆÔØŸš¨¬Ô)>Ñ?Ô?ˆŒØ!Ÿ_š_¨T¬[Ô-FÑGÔGˆÔØ#'§?¢?°4´;Ô3RÑ#SÔ#SˆÔ Ø!Ÿ_š_¨T¬[Ô-FÑGÔGˆÔÝ �5Ð*Ñ +Ô +ð EØ"&§/¢/°$´+Ô2LÑ"MÔ"MˆDÔ Ø#'§?¢?°4´;Ô3NÑ#OÔ#OˆDÔ Ø#Ÿš¨t¬{Ô/FÑGÔGˆDÔ Ø $§¢°´ Ô0HÑ IÔ IˆDÔ ð"&§¢°Ô1CÑ!DÔ!DˆDÔ Ý �5Ð+Ñ ,Ô ,ð PØ#'§?¢?°4´;Ô3NÑ#OÔ#OˆDÔ Ð Ð ð Pð Pr có,—t|jd¦«S)zB Check in pylve binding reseller limits supported rT)rdr#)r(s r Úresellers_supportedzPyLve.resellers_supported{s€õ�t”{Ð$4Ñ5Ô5Ð5r cóx—t|jd¦«sdS|j ¦«\}}||fdkS)aÉ Check if per-domain limits via hierarchical LVP (lve_lvp_create2) are supported by both the installed library and the running kernel module. liblve and lve-kmod may be at different versions when one is updated without rebooting. lve_lvp_create2 requires kernel module API >= 1.7. After pylve.initialize(), lve_kapi_ver() returns the API version that kapi_init() negotiated with the running kernel. rUF)r5é)rdr#Ú lve_kapi_ver)r(Ú kapi_majorÚ kapi_minors r Údomains_supportedzPyLve.domains_supported�sF€õ�t”{Ð$5Ñ6Ô6ð Ø�5à!%¤×!9Ò!9Ñ!;Ô!;ш �JؘJÐ'¨6Ò1Ð1r cóT— | |¦«dS#t$rYdSwxYw)zD Check if lve exists in kernel :rtype: bool TF)r^ÚOSError)r(Úlve_ids r Ú lve_existszPyLve.lve_exists‘s@€ð  Ø �MŠM˜&Ñ !Ô !Ð !Ø�4øÝð ð ð Ø�5�5ð øøøs ‚™ '¦'cóH— |j |d¬¦«D]d}| ¦«}t|d d¦«d¦«tkrt|d¦«cSŒen#t t tf$rYdSwxYwdS)u|Current CPU limit of lvp, or None if it cannot be read. liblve exposes no lve_lvp_info() binding (the kernel does implement the ioctl), so the only way to see an LVP's own limits without changing them is /proc/lve/resellers/lvp/list, where they are carried in the LIMIT_LVP_ID row — the row `lvectl list-domains` prints as `limit`, and the same row lve_lvp_setup writes. Column 1 is lCPU, in the same hundredths-of-a-percent units as liblve_settings.ls_cpu. Split on whitespace, not on tabs: some rows carry a spurious empty cell after the id (26 tab-separated cells against the header's 25), and str.split() collapses it so every row aligns to the header. :param int lvp_id: top level container ID. :return: int CPU limit, or None when the row is absent or unparsable. F)Úlvp_idÚwithout_limitsrú,éÿÿÿÿr5N)rWÚlinesÚsplitrrrvÚ IndexErrorÚ ValueError)r(rzÚlineÚfieldss r Ú_lvp_cpu_limitzPyLve._lvp_cpu_limitœs±€ð$ Øœ ×(Ò(°ÀuÐ(ÑMÔMð *ð *�ØŸš™œ�Ý�v˜a”y—’ sÑ+Ô+¨BÔ/Ñ0Ô0µLÒ@Ð@ݘv aœy™>œ>Ð)Ð)Ð)ðAð *øõ�¥ZÐ0ð ð ð Ø�4�4ð øøøàˆts‚A?BÂBÂBÂBcóâ—|dkr|j ||¦«S| |¦«|jkr+| |jj¦«||d¬¦«Si}t ¦«}|j |¦«D]¨} | |¦«}|||<|jptd¦«}||jkrZ| |¦«}t||j¦«|_|  ||¦«|  |¦«Œ™#t$rYŒ¥wxYw| |jj¦«} | ||d¬¦«} |j |¦«D]i}||vr:||} ||vr| || |¦«|  || ¦«Œ@|  || |¦«¦«Œj| S)a~ Wrapper for lve_lvp_setup. When a LVP's limits change (reseller or domain-isolated user), we must iterate over child LVEs, temporarily reduce any that exceed the new parent limit, set the LVP, then restore the original child limits. This is needed because the kernel does not update child LVE limits when the parent LVP limit changes (KMODLVE-79) and rejects the call when any child exceeds the new parent limit. :param int lvp_id: top level container ID, 0 by default; :param settings: liblve_settings instance. :return: 0 or errno value rT©r.Úinf)r#rhr„Úls_cpurRÚsetrWÚ lve_id_listr^ÚfloatÚminr`ÚaddrvÚ_invalidate_child_cpu) r(rzÚsettingsÚreal_lve_settingsÚreduced_childrenrwÚ real_settingsÚ child_cpuÚ temp_settingsÚ_lve_lvp_setupÚresultÚreals r rhzPyLve.lve_lvp_setup¹s€ð" �QŠ;ˆ;Ø”;×,Ò,¨V°XÑ>Ô>Ð >ð2 × Ò ˜vÑ &Ô &¨(¬/Ò 9Ð 9Ø=�4—?’? 4¤;Ô#<Ñ=Ô=ؘ¨tðñôð ð #%ÐÝ #¡¤ÐØ”j×,Ò,¨VÑ4Ô4ð ð ˆFð Ø $§ ¢ ¨fÑ 5Ô 5� Ø,9Ð! &Ñ)ð *Ô0Ð@µE¸%±L´L� ؘxœÒ.Ð.Ø$(§M¢M°&Ñ$9Ô$9�MÝ+.¨y¸(¼/Ñ+JÔ+J�MÔ(Ø—N’N 6¨=Ñ9Ô9Ð9Ø$×(Ò(¨Ñ0Ô0Ð0øøÝð ð ð à�ð øøøð Ÿš¨¬Ô)BÑCÔCˆØ� ¨¸tÐDÑDÔDˆð”j×,Ò,¨VÑ4Ô4ð >ð >ˆFØÐ*Ð*Ð*Ø(¨Ô0�ØÐ!1Ð1Ð1Ø×.Ò.¨v°t¸XÑFÔFÐFØ—’˜v tÑ,Ô,Ð,Ð,ð —’˜v t§}¢}°VÑ'<Ô'<Ñ=Ô=Ð=Ð=àˆ sÂBD.Ä. D;Ä:D;cóЗ| |¦«}|j|jkr |j|_ntd|jdz ¦«|_| ||¦«dS)aForce the kernel to re-apply a child's CPU cgroup value. Sets CPU to a value different from the child's current lve_limits so that the subsequent lve_setup with the real value is not treated as a no-op by lve_resources_setup(). r5N)r^rˆÚmaxr`)r(rwr—Úparent_settingsÚbumps r rŽzPyLve._invalidate_child_cpusd€ð�}Š}˜VÑ$Ô$ˆØ Œ;˜/Ô0Ò 0Ð 0Ø)Ô0ˆDŒKˆKå˜a Ô!7¸!Ñ!;Ñ<Ô<ˆDŒKØ �Š�v˜tÑ$Ô$Ð$Ð$Ð$r cóŽ— ddlm}t| ¦«¦«S#t$rt¦«cYSwxYw)a Domain LVE ids already assigned in /etc/container/lvd_ids. Imported lazily: websiteisolation imports this module at the top level, so a module-level import here would form a cycle (see the module docstring). A registry read failure must not make id allocation unusable, so any error degrades to "nothing reserved" - the behaviour before this filter existed. r©Ú id_registry)Úwebsiteisolationržr‰Úget_all_domain_idsÚ Exceptionr�s r Ú_reserved_domain_lve_idszPyLve._reserved_domain_lve_ids+s[€ð Ø 4Ð 4Ð 4Ð 4Ð 4Ð 4Ý�{×5Ò5Ñ7Ô7Ñ8Ô8Ð 8øÝð ð ð Ý‘5”5ˆLˆLˆLð øøøs‚&)©AÁAcóà—| ¦«}t|dz|¦«D]1}||vrŒ | |¦«Œ#t$r|cYcSwxYwt d|›d|›d�¦«‚)a­ Iter over lves and find available one. A candidate is skipped when it is live in the kernel OR already assigned to a domain in the per-domain id registry. Both checks are needed: this allocator hands out transient top-level LVE ids (see lvectllib.temporary_lve, used by cloudlinux-summary and cloudlinux_domains_collector) from the same numeric pool as domain LVE ids, and a domain id that is registered but not yet materialised in the kernel is invisible to lve_info(). Handing such an id out shadows the domain LVE - its requests then enter a top-level LVE with server default limits, outside the owner's LVP - or clobbers the domain LVE's limits through the caller's lve_setup. :param int start: value to start search from; UID_MAX by default :param int stop: max value when we will stop search :return int: lve_id r5z"Unable to find free lve in range (rú))r¢Úranger^rvr)r(ÚstartÚstopÚreservedrws r Úget_available_lve_idzPyLve.get_available_lve_id=s¤€ð&×0Ò0Ñ2Ô2ˆÝ˜E A™I tÑ,Ô,ð ð ˆFؘÐ!Ð!Øð Ø— ’ ˜fÑ%Ô%Ð%Ð%øÝð ð ð Ø� � � � � ð øøøåÐN¸eÐNÐNÀtÐNÐNÐNÑOÔOÐOs°AÁ AÁAc#óXK—||jc|_} dV—||_dS#||_wxYwrPr†)r(r.Úsaved_ignore_errors r Úcontext_ignore_errorzPyLve.context_ignore_errorZsJèè€à0<¸dÔ>OÐ-ˆÔÐ-ð 3Ø ˆEˆEˆEà 2ˆDÔ Ð Ð øÐ 2ˆDÔ Ð 2Ð 2Ð 2Ð 2s“   )N)rr r Ú__doc__Ú staticmethodrr+rMrRÚ _pylve_modulerlrnrtrxr„rhrŽr¢ÚUID_MAXÚ MAX_LVE_IDr©Ú contextlibÚcontextmanagerr¬r r r rr'sD€€€€€ððððMðMñ„\ðMððððððð4ððð +°$À3Èað!Pð!Pð!Pð!PðF6ð6ð6ð 2ð2ð2ð ð ð ðððð:bðbðbðH %ð %ð %ðððñ„\ðð"*1°zðPðPðPðPð:Ôð3ð3ñÔð3ð3ð3r r)r­r²rr:Úclcommon.clprocrrÚclcommon.clfuncrrir¯Ú ImportErrorr°r±r¡rrr r r úr·s ððððÐÐÐØ € € € Ø € € € à1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ø#Ð#Ð#Ð#Ð#Ð#ðØ!Ð!Ð!Ð!Ð!øØðððØ€M€M€Mðøøøð ˆ'‰)Œ)€ð€ ð ð ð ð ð �ñ ô ð ðy3ðy3ðy3ðy3ðy3ñy3ôy3ðy3ðy3ðy3s ž#£-¬-