§ À•¿j‚`ãó2—ddlmZddlmZddlmZddlZddlZddlZddlZddlm Z m Z ddl m Z ddl Z ddlmZmZddlmZdd lmZmZmZdd lmZdd lmZmZmZdd lmZdd lm Z Gd„de!¦«Z"Gd„de!¦«Z#Gd„de¦«Z$dd„Z%dS)é)Úprint_function)Údivision)Úabsolute_importN)ÚAnyStrÚOptional)Ú iteritems)Ú get_abs_relÚrun_process_in_cagefs)Údrop_privileges)ÚBaseSelectorErrorÚMissingVirtualenvErrorÚMissingAppRootError)Ú WSGI_PATH)ÚClSelectExceptÚ clpassengerÚ clselectctl)ÚBaseApplicationsManager)Ú PythonManagercó—eZdZdZdZdZdS)ÚPythonAppFormatVersionz@ Class represents possible python application versions. ééN©Ú__name__Ú __module__Ú __qualname__Ú__doc__ÚLEGACYÚSTABLE©óú[/opt/cloudlinux/venv/lib64/python3.11/site-packages/clselect/clselectpython/apps_manager.pyrr#s$€€€€€ððð €Fà €F€F€Fr!rcó—eZdZdZdZdZdS)ÚPythonVenvFormatVersionzJ Class represents possible python application venv path versions. rrNrr r!r"r$r$.s&€€€€€ððð €Fð€F€F€Fr!r$có̇—eZdZdZdZdZdZdZdZdZ dZ ˆfd„Z dˆfd „ Z e d „¦«Zd „Zd „Zdd„ZdZdd„Zd„Zd„Zd„Zd„Zdd„Zd„Zdˆfd„ ZdZd„Zd d„Zdd„ZˆxZS)!ÚApplicationsManagerz!.cl.selector/python-selector.jsonz/var/lve/.py.migration.statusz!.cl.selector/.py.migration.statusz//var/log/cloudlinux/py-selector/app_imports.logzimported_pip_requirements.txtÚpythonÚ virtualenvcóp•—tt|¦« t¦«¦«dS©N)Úsuperr&Ú__init__r)ÚselfÚ __class__s €r"r,zApplicationsManager.__init__Ds,ø€Ý Õ! 4Ñ(Ô(×1Ò1µ-±/´/ÑBÔBÐBÐBÐBr!r cóZ•—tt|¦« |||¬¦«S)N)Úpatterns)r+r&Ú_find_config_files)r-Ú user_nameÚ app_directoryr0r.s €r"r1z&ApplicationsManager._find_config_filesHs*ø€åÕ(¨$Ñ/Ô/×BÒBÀ9ÈmÐfnÐBÑoÔoÐor!có2—d |¦«g}|S)zÖ Return lines for htaccess that are specific to the python interpreter :param binary_path: path to the environment's python binary :param app_config: application's config dictionary zPassengerPython "{}" )Úformat)Ú binary_pathÚ app_configÚspecific_liness r"Ú(get_interpreter_specific_passenger_lineszÅÀZÇ_Â_ÑEVÔEVÑ@WÔ@WÑXÔXÐX؈ ØÐ؈ å! *Ñ-Ô-ð9 *ñ9 *‰HˆD�"å œgŸlšl¨2¬9°nÑEÔEˆOÝ”7—=’= Ñ1Ô1ð Ø# qÑ(Ð#Ø×"Ò"Ð"ÐVZÐVZÐVZÐ\kÐ\kÐ\kÐ#lÑmÔmÐmØØ �OŠOÐ/°Ñ 6Ô 6Ð 6ð0 *õ% TÑ*Ô*ð !ð !­HÔ,BÑ,DÔ,Dð !ð !ð$Ø!%×!DÒ!DØœI r¤y°"´)ñ"=ô"=˜˜øå,ð$ð$ð$Ø!#˜˜˜ð$øøøð)-×(EÒ(EÀdÈJÑ(WÔ(WÑ%�D˜+Øð!Ø ð !ð !ð !ñ !ô !ð !ð !ð !ð !ñ !ô !ð !ñ !ð!ð !ð !ð !ñ !ô !ð !ð !ð !ð !ð !ð !øøøð !ð !ð !ð !ð !ð !ð !ñ !ô !ð !ð !ð !ð !ð !ð !øøøð !ð !ð !ð !õ-6°d©O¬Oð2ð2Ñ(�H˜jØ 6Ð)Ð)à5;¸HÔ5EÀnÔ5U˜  >Ñ2Ø17¸Ô1AÀ*Ô1M˜  :Ñ.ð×2Ò2°4¸À:ÑNÔNÐNÝ(*¬¯ ª °R´YÀÈ$ÔJhÑ(iÔ(iÐ%Ý”w—~’~Ð&7Ñ8Ô8ðZØ Ô:À*È^ÔB\Ð\Ð\à" >Ô2×9Ò9¸$Ô:XÑYÔYÐYà'1�F˜8Ñ$Ð$õ "% V§[¢[¡]¤]Ñ!3Ô!3µc¸$¿)º)¹+¼+Ñ6FÔ6FÑ!F�Ø .ð)ð)�HØ—J’J˜xÑ(Ô(Ð(Ð(å$ TÑ*Ô*ðmðm­HÔ,BÑ,DÔ,DðmðmØ×4Ò4°T¸6ÑBÔBÐBØ×7Ò7¸ÈUÐ`kÐ7ÑlÔlÐlðmðmðmñmômðmðmðmðmðmðmøøøðmðmðmðmðmðmðmñmômðmðmðmðmðmðmøøøðmðmðmðmùøõð *ð *ð *ð X� ð×$Ò$ \°4¸Ñ;Ô;Ð;Ý$ TÑ*Ô*ðlðl­HÔ,BÑ,DÔ,DðlðlØ×7Ò7¸ÈTÐ_jÐ7ÑkÔkÐkðlðlðlñlôlðlðlðlðlðlðløøøðlðlðlðlðlðlðlñlôlðlðlðlðlðlðløøøðlðlðlðlà×#Ò# DÑ)Ô)Ð)Ð)Ð)Ð)Ð)Ñ)øøøøð *øøøð ×,Ò,¨\Ñ:Ô:Ð:Ø  !Ò #Ð #Ø × Ò ÐEÑ FÔ FÐ FÐ FÐ Fð $Ð #s!Ã6M&ÄF,ÄFÄ&EÅFÅ E ÅFÅE ÅFÅ0 F,Å; M&Æ F,ÆF ÆF,ÆF ÆF,Æ M&Æ,F0 Æ0M&Æ3F0 Æ4D?M&Ë3MÌ/MÌ6 MÍM ÍMÍ M Í MÍ M&ÍM ÍM&Í M Í!M&Í& PÍ0(PÎO(Î,O Ï O(ÏO ÏO(ÏO ÏO(Ï PÏ(O, Ï,PÏ/O, Ï0PÐPicóP—|€htj |j¦«sdSt |j¦«5}t j|¦«cddd¦«S#1swxYwYdStj|¦«}tj  |j |j ¦«} tj |¦«}n#t$rYdSwxYwddlm}||j¦«sdS|j|jkrdStj¦«dkrZdt(_t)j||j|jdd¬¦«}|€dSt jd  |¦«¦«St |¦«5}t j|¦«cddd¦«S#1swxYwYdS)zz Read import log which contains information about failed users or apps depending on current user. Nr)ÚS_ISREGTF)Ú exit_on_errorÚ write_logr@)rSrTÚexistsÚ_IMPORT_STATUS_ADMINrXÚjsonÚloadÚpwdÚgetpwnamrUrŒÚ_IMPORT_STATUS_USERÚlstatÚOSErrorÚstatr©Úst_modeÚst_sizeÚ_IMPORT_STATUS_USER_MAX_BYTESÚgeteuidr�Ú SILENT_FLAGÚread_file_securer’r“Úloads)r-rcrjÚuser_pwÚmarkerÚ marker_str©Ú marker_liness r"Ú_get_legacy_import_statusz-ApplicationsManager._get_legacy_import_statusþs5€ð ˆ<Ý”7—>’> $Ô";Ñ<Ô<ð Ø�tå�dÔ/Ñ0Ô0ð $°AÝ”y ‘|”|ð $ð $ð $ð $ñ $ô $ð $ð $ð $ð $ð $ð $øøøð $ð $ð $ð $ð $ð $õ”l 4Ñ(Ô(ˆGÝ”W—\’\ '¤.°$Ô2JÑKÔKˆFð ÝœH VÑ,Ô,� � øÝð ð ð Ø�t�tð øøøð %Ð $Ð $Ð $Ð $Ð $Ø�7˜9Ô,Ñ-Ô-ð Ø�tØÔ  4Ô#EÒEÐEð�tõ Œz‰|Œ|˜qÒ Ð Ø'+•Ô$õ (Ô8¸ÀÄÐQXÔQ_ØGLÐX]ð _ñ _ô _� àÐ'ؘ4Ý”z "§'¢'¨,Ñ"7Ô"7Ñ8Ô8Ð8Ý�f‘”ð $ Ý”y ‘|”|ð $ð $ð $ð $ñ $ô $ð $ð $ð $ð $ð $ð $øøøð $ð $ð $ð $ð $ð $s5½AÁA"Á%A"Â*B?Â? C à C Å:FÆFÆ"Fcó’—tj tj |jd¦«¦«sdS tj |j|j¦«}t jtj ||dœ¦«|d¦«dS#ttf$rtj d¦«YdSwxYw)z‰ Save information that some applications were not imported automatically to show warning for user in the future. r…N)r†Úapps_lookup_failedé€z$Unable to save migration status file)rSrTr¬rUrŒr²r�Úwrite_file_via_tempfiler®ÚdumpsÚIOErrorr´rur`)r-r½r†r‡r¾s r"r™z2ApplicationsManager._set_user_legacy_import_status0sÖ€õ Œw�~Š~�bœgŸlšl¨7¬>¸>ÑJÔJÑKÔKð Ø ˆFð FÝ”W—\’\ '¤.°$Ô2JÑKÔKˆFÝ Ô ,­T¬ZØ$4Ø&1ð9ð9ñ.ô.ð˜ñ ô ð ð ð øõ�Ð!ð Fð Fð Få Ô ÐDÑ EÔ EÐ EÐ EÐ EÐ Eð FøøøsÁABÂ%CÃCcóh—tjd|i¦«}tj||jd¦«dS)zƒ Save information that some users were not imported automatically to show warning for admin in the future. rœrÄN)r®rÆr�rÅr­)r-rœÚpackeds r"ršz3ApplicationsManager._set_admin_legacy_import_statusAs6€õ ”˜^¨\Ð:Ñ;Ô;ˆÝÔ(¨°Ô1JÈEÑRÔRÐRÐRÐRr!có¼—| ¦«}|�|dsdSd d |d¦«|j|j¬¦«}|S)NrœaœUnexpected issue(s) happened during importing python applications for the following users: "{users}". Everything will work as before, but listed users wo't be able to control applications from Python Selector UI. Please, contact CloudLinux support and send them log file located at `{log_file_path}` to investigate and resolve this issue. Also you can hide this warning by deleting `{import_warning_marker}` fileú,)ÚusersÚ log_file_pathÚimport_warning_marker)rÁr5rUrzr­)r-r Ú warning_msgs r"Ú _get_admin_legacy_import_warningz4ApplicationsManager._get_admin_legacy_import_warningIso€Ø×/Ò/Ñ1Ô1ˆà ˆ> ¨Ô!7ˆ>Ø�4ð÷ š c§h¢h¨v°nÔ/EÑ&FÔ&FØ.2Ô.CØ6:Ô6Oð ñQôQð ðÐr!cóÜ—| |¬¦«}|€dSd |j¬¦«}|drd|zS|dr!dd |d¦«›d |›�SdS) N)rcaEverything will work as before, but you won't be able to control listed applications from Python Selector UI. Please, ask you hoster to contact CloudLinux support to investigate and resolve this issue. Also you can hide this warning by deleting `~/{import_warning_marker}` file.)rÎr†zEUnexpected issue(s) happened during importing python applications. %srÃzNUnexpected issue(s) happened during importing following python applications: "rËz". )rÁr5r²rU)r-Úusernamer Úwhat_to_do_msgs r"Ú_get_user_legacy_import_warningz3ApplicationsManager._get_user_legacy_import_warning[s®€Ø×/Ò/°XÐ/Ñ>Ô>ˆØ ˆ>Ø�4ð ÷ Šv¨DÔ,DˆvÑEÔEð ð Ð$Ô %ð Sðà(ñ)ð )ðÐ(Ô )ð Sð SðŸ8š8 FÐ+?Ô$@ÑAÔAÐAÐAÀ>À>ðSð Sðˆtr!cóX—|€| ¦«S| |¦«Sr*)rÐrÔ)r-rcs r"Ú"_get_legacy_import_warning_or_nonez6ApplicationsManager._get_legacy_import_warning_or_noness-€Ø ˆ<Ø×8Ò8Ñ:Ô:Ð :à×7Ò7¸Ñ=Ô=Ð =r!có¼—ddlm}| ||¦«}|€tjd|z¦«‚|dt jkrtjd|z¦«‚||||¬¦«} | d¬ ¦«n-#t$r }tjd |›d |›d �¦«‚d}~wwxYwt j|d<|  |||¦«dS) zo Update environment of specific application to support features of new python selector r©Ú_get_environmentNzApplication %s does not existrCzCApplication %s is already new version and does not need any updates©Ú apps_managerT)Ú auto_restorezUnable to migrate application z . Error is 'z‹', everything restored to work as before migration. Try again later or ask your hoster to contact CloudLinux support if the issue persists.) rOrÙÚget_app_configrÚ WrongDatarrÚconfigure_environmentr_Úadd_app_to_config)r-rcr¢rÙrFÚ environmentr¥s r"Úmigrate_applicationz'ApplicationsManager.migrate_applicationys/€ð @Ð?Ð?Ð?Ð?Ð?Ø×)Ò)¨$°Ñ9Ô9ˆ Ø Ð Ý Ô*Ð+JÈXÑ+UÑVÔVÐ Và �}Ô %Õ)?Ô)FÒ FÐ FÝ Ô*ð0Ø2:ñ;ñ<ô<ð <ð'Ð& t¨XÀDÐIÑIÔIˆ ð $Ø × -Ò -¸4Ð -Ñ @Ô @Ð @Ð @øÝð $ð $ð $Ý Ô*Ð*ð �h�h   ð #ñ$ô$ð $øøøøð $øøøõ&<Ô%Bˆ �MÑ"Ø ×Ò˜t X¨{Ñ;Ô;Ð;Ð;Ð;sÁ2B  B3ÂB.Â.B3có�•—tt|¦« |¦«}| |¦«}|�||d<|S)NrW)r+r&Úget_applications_users_inforÖ)r-rcÚresultrWr.s €r"räz/ApplicationsManager.get_applications_users_info–sLø€ÝÕ*¨DÑ1Ô1ß 'Ò '¨Ñ -Ô -ð à×9Ò9¸$Ñ?Ô?ˆØ Ð Ø 'ˆF�9Ñ Øˆ r!icóh—t||¦«\}}tj ||j¦«}tj |¦«rdSddlm}t|¦«5||||¬¦«}|  ¦«} ddd¦«n #1swxYwYtj |¦«j } d| i} d} t|| ddg| ¬ ¦«} |  d ¦«}t|t ¦«rPt#|¦«|jkr8| d ||j¦«t)jd |jz¦«‚| d dkr9| dt!|¦«z¦«t)j|¦«‚| ds|} t|¦«5t-j¦«5t1|d¦«}| | ¦«| ¦«ddd¦«n #1swxYwYddd¦«dS#1swxYwYdS)z¤ Generates requirements file from python apps :param user: username :param app_root: app root :param app_logger: app logger NrrØrÚÚHOMEr@Úfreezez-l)rMÚoutputzDpip freeze output for user %s exceeded %d bytes; refusing to import.z,pip freeze output exceeded the %d-byte limitÚ returncodez/Error during generation pip requirements file. ÚfailedÚw)r rSrTrUr•r¬rOrÙr Úpipr°r±rŒr ÚgetÚ isinstanceÚstrÚlenÚ_PIP_FREEZE_MAX_BYTESrWrÚExternalProgramFailedr�r�rXÚwriteÚclose)r-rcr¢r€Úapp_pathÚ_Úreq_pathrÙráÚpip_pathÚ user_homerMÚmodulesrårérjs r"r”z-ApplicationsManager.generate_pip_requirementsªs €õ" $¨Ñ1Ô1‰ ˆ�!Ý”7—<’< ¨$Ô*HÑIÔIˆÝ Œ7�>Š>˜(Ñ #Ô #ð Ø ˆFà?Ð?Ð?Ð?Ð?Ð?Ý ˜TÑ "Ô "ð )ð )Ø*Ð*Ø�h¨Tð3ñ3ô3ˆKð#—’Ñ(Ô(ˆHð  )ð )ð )ñ )ô )ð )ð )ð )ð )ð )ð )øøøð )ð )ð )ð )õ ”L Ñ&Ô&Ô-ˆ ؘIÐ&ˆàˆå& t¨X¸À$Ð7GÐRZÐ[Ñ[Ô[ˆð—’˜HÑ%Ô%ˆÝ �f�cÑ "Ô "ð ]¥s¨6¡{¤{°TÔ5OÒ'OÐ'OØ × Ò ØVØ�dÔ0ñ 2ô 2ð 2õ!Ô6Ø>ÀÔA[Ñ[ñ]ô]ð ]à �,Ô  1Ò $Ð $Ø × Ò ÐPÕSVÐW]ÑS^ÔS^Ñ^Ñ _Ô _Ð _å Ô6°vÑ>Ô>Ð >ؘÔ!ð ØˆGõ˜TÑ "Ô "ð ð ¥HÔ$:Ñ$<Ô$<ð ð Ý�X˜sÑ#Ô#ˆAØ �GŠG�GÑ Ô Ð Ø �GŠG‰IŒIˆIð ð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð ð ð ñ ô ð ð ð ð ð ð ð øøøð ð ð ð ð ð sHÁ/#BÂB"Â%B"Æ5H'Ç :HÈ H'ÈH ÈH'ÈH ÈH'È'H+È.H+Tcó®—|j |¦«j}t||¦«\}}tj ||¦«}|r.tj |¦«st|¦«‚tj ||¦«}|r.tj |¦«st|¦«‚||fS)a Calculate, check exists and return application folders This method does not check that application exists in config. :raises: NoSuchUserException, MissingVirtualenvError, MissingAppRootError :return: tuple(app_root, app_venv) with absolute paths ) Ú_pwdÚget_pw_by_namerŒÚget_venv_rel_pathrSrTrUr¬r r) r-rÒr¢Úchk_envÚ chk_app_rootrúr÷Úrel_pathÚapp_venvs r"Úget_app_foldersz#ApplicationsManager.get_app_foldersÝsº€ð”I×,Ò,¨XÑ6Ô6Ô=ˆ Ý'¨°(Ñ;Ô;‰ ˆˆ8Ý”7—<’<  ¨8Ñ4Ô4ˆØ ð 3�2œ7Ÿ>š>¨(Ñ3Ô3ð 3Ý(¨Ñ2Ô2Ð 2å”7—<’<  ¨8Ñ4Ô4ˆØ ð 0¥¤§¢¨xÑ 8Ô 8ð 0Ý% hÑ/Ô/Ð /à˜Ð!Ð!r!có¬—| ||¦«}|€|j}t||¦«\}}tj |||d|¦«S)a­ Return a path to the environment's interpreter binary Get interpreter path for application :param user: owner of the application :param app_root: app path relative to user home (app-root) :param user_dir: User's home directory :param binary_name: name of binary in virtual environemnt (python, npm, node) :return: path to interpreter binary in virtual environment NÚbin)Úget_interpreter_version_for_appÚ BINARY_NAMErÿrSrTrU)r-rcr¢Úuser_dirÚ binary_nameÚversionr÷rs r"Úget_binary_pathz#ApplicationsManager.get_binary_pathðsV€ð×6Ò6°t¸XÑFÔFˆØ Ð ØÔ*ˆKÝ'¨¨hÑ7Ô7‰ ˆˆ8ÝŒw�|Š|˜H h°¸À ÑLÔLÐLr!)r r*)TT) rrrÚ _USER_CONFIGr­r²rzr•rRÚVENV_DIRrr,r1Ú staticmethodr9rrrƒr§r¸rÁr™ršrÐrÔrÖrâräròr”rr Ú __classcell__)r.s@r"r&r&:sÏø€€€€€Ø6€LØ:ÐØ=ÐØHÐØ ?ÐØ€KØ€HØ€KðCðCðCðCðCðpðpðpðpðpðpðððñ„\ððD$ðD$ðD$ðL ð ð ðJGðJGðJGðJGðb%*Ð!ð0$ð0$ð0$ð0$ðdFðFðFð"SðSðSðððð$ððð0>ð>ð>ð>ð <ð<ð<ð:ðððððð,Ðð 1ð1ð1ðf"ð"ð"ð"ð&MðMðMðMðMðMðMðMr!r&c óX—t|tj tj|¦«¦«\}}t|tj tjt j|¦«¦«¦«\}}|€Stj |¦«r&|t j|¦«krtj |fStj |fS|tj krtj |fS|tj krtj |fStd|z¦«‚)a6 Get path to users VENV relative to home dir. Old python selector transforms app_root using get_prefix() method before creating venv directory. We should handle both cases: - when app is from old selector - when app is from new selector and return right env directory. If both old and new vevns exist we use old one. Return tuple with two values: - detected version of venv path (LEGACY for path with replacements "/" -> "_" & "_" => "__" and STABLE in other case) - path to venv relative to user's home dir Nzunknown version `%s`) r rSrTrUr&rrÚ get_prefixr¬r$rrÚ ValueError)rcr=r r÷Ú new_rel_dirÚ old_abs_dirÚ old_rel_dirs r"rÿrÿs€õ! ¥r¤w§|¢|Õ4GÔ4PÐR[Ñ'\Ô'\Ñ]Ô]�N€A€{Ý*Ø �bŒg�lŠlÕ.Ô7½Ô9OÐPYÑ9ZÔ9ZÑ[Ô[ñ ]ô ]Ñ€K�à€Ý Œ7�>Š>˜+Ñ &Ô &ð ?¨9½ Ô8NÈyÑ8YÔ8YÒ+YÐ+YÝ*Ô1°;Ð>Ð >Ý&Ô-¨{Ð:Ð:Ø Õ+Ô2Ò 2Ð 2Ý&Ô-¨{Ð:Ð:Ø Õ+Ô2Ò 2Ð 2Ý&Ô-¨{Ð:Ð:åÐ/°'Ñ9Ñ:Ô:Ð:r!r*)&Ú __future__rrrrurSr°r®ÚtypingrrÚ future.utilsrr�Úclselect.utilsr r Úclcommon.clpwdr Úclselect.baseclselectr r rÚclselect.clpassengerrÚclselectrrrÚ"clselect.baseclselect.apps_managerrÚ&clselect.clselectpython.python_managerrÚobjectrr$r&rÿr r!r"úr"sôðð&Ð%Ð%Ð%Ð%Ð%ØÐÐÐÐÐØ&Ð&Ð&Ð&Ð&Ð&Ø€€€Ø € € € Ø € € € Ø € € € à#Ð#Ð#Ð#Ð#Ð#Ð#Ð#Ø"Ð"Ð"Ð"Ð"Ð"à€€€à=Ð=Ð=Ð=Ð=Ð=Ð=Ð=Ø*Ð*Ð*Ð*Ð*Ð*ððððððððððð +Ð*Ð*Ð*Ð*Ð*Ø=Ð=Ð=Ð=Ð=Ð=Ð=Ð=Ð=Ð=ØFÐFÐFÐFÐFÐFØ@Ð@Ð@Ð@Ð@Ð@ððððð˜Vñôðð ð ð ð ð ˜fñ ô ð ðDMðDMðDMðDMðDMÐ1ñDMôDMðDMðP;ð;ð;ð;ð;ð;r!