HeNjvJddlmZddlmZddlmZddlZddlZddlZddlZddl m Z m Z ddl m Z ddl mZddlZddlmZddlmZdd lmZdd lmZmZdd lmZmZmZdd lmZdd lm Z m!Z!m"Z"m#Z#ddl$m%Z%ddlm&Z&m'Z'ddlm(Z(ddlm)Z)Gdde)e e*Z+dS))absolute_import)print_function)divisionN)ABCMetaabstractmethod)datetime iteritems)unicode)ClPwd)get_file_lineswrite_file_lines) pretty_jsondelete_using_realpath_keys get_abs_rel)ClSelectExcept)BaseSelectorErrorAbsentFileErrorMissingVirtualenvErrorMissingAppRootError)BaseSelectorManager)file_readlinesfile_writelines)get_using_realpath_keys)with_metaclasscLeZdZdZdZdZdZdZdZdZ e dZ dZ dZ dZd'd Zed(d Zd Zeed Zd(dZd(dZdZdZdZdZdZdZdZdZdZdZ dZ!dZ"edZ#d(dZ$d(dZ%dZ&d Z'd!Z(d(d"Z)d)d$Z*d%Z+d&Z,dS)*BaseApplicationsManagerz[ Base class that responsible for gathering and set information about applications. Nz/var/log/selectorctl.logc:||_t|_dSN)_managerr _pwd)selfmanagers Y/opt/cloudlinux/venv/lib64/python3.11/site-packages/clselect/baseclselect/apps_manager.py__init__z BaseApplicationsManager.__init__3s GG c tjd}t|j|d|dgddS#t t f$rYdSwxYw)zi Writes string to log file :param log_str: String to write :return: None z%Y-%m-%d %H:%M:%S:  aN)rnowstrftimer_LOG_FILE_NAMEIOErrorOSError)clslog_str dt_strings r%write_string_to_logz+BaseApplicationsManager.write_string_to_log7st  //0CDDI S/ 7772S1TVY Z Z Z Z Z!    DD sAAAAcf||}|||<|||dS)a Add data to user's config (update info for an app with app_directory specified) :param str user: name of unix user :param str app_directory: Application root directory :param dict app_data: Application data :return: None N)get_user_config_datawrite_full_user_config_data)r#user app_directoryapp_data current_dicts r%add_app_to_configz)BaseApplicationsManager.add_app_to_configDs=0066 &. ]# ((|<<<<zEBaseApplicationsManager.add_env_vars_for_htaccess..`sJJJdTJTJJJr'r*rz zSetEnv {0} {1}z w) get_htaccess_by_appdiropenreadsplitindexappenditemsreplaceformatwritejoin)r# user_namer9env_varsdoc_rootenv_section_beginenv_section_end htaccess_filehtaccesslinesstartendenv_varvalues r%add_env_vars_for_htaccessz1BaseApplicationsManager.add_env_vars_for_htaccessQsa\33I}hX\]]  F --> ? ? ? .8JJhmmoo&;&;D&A&AJJJE E))o.F.F $566kk/22%q.)# ./// 3444&.nn&6&6JJNGU%oodB77??bIIG!MM$33;;D"EEELL!1!8!8%!H!HIIII ]+++ _--- . . . . . . . . . . . . . . .--> ? ? ? -8 NN499U++ , , , - - - - - - - - - - - - - - - - - -s$EFFF5)G++G/2G/c||} t||||||dS#t$rYdSwxYw)z Removes application from config :param user: User name :param app_dir: Application directory :return: True if app is exists in config, False - if app is not exists in config TF)r6rr7KeyError)r#r8app_dir config_datas r%remove_app_from_configz.BaseApplicationsManager.remove_app_from_configqso//55   &tWk B B B  , ,T; ? ? ?4   55 s'A A AFc ||}|sdSt|D]\}}|rtjd|z|d}ntjd|z|d}|Bt d|ddt | ||d<|||dS)a Replace domain in config files when it is renamed. :param username: domain owner :param domain: previous name :param new_domain: name after rename :param include_subdomains: whether we should also rename subdomains :return: Nz (\.|^)%s$domainz^%s$z{}{})r6r researchr rRlenr7) r#usernamerh new_domaininclude_subdomains full_configappconfigmatchs r%replace_domain_in_configsz1BaseApplicationsManager.replace_domain_in_configss//99   F%[11 ! !KC! F ,"79IJJ 'F"2F84DEE #*6==8$]s6{{l]3, , $!$!x  ((;?????r'cFt||\}fd|DS)z6 Return list of detected config files cg|]A}tjtj|?|BSrC)ospathexistsrT)rDrqabs_paths r%rFz>BaseApplicationsManager._find_config_files..s=```6 XW]@^@^1_1_````r')r)rUr9patternsrel_pathrys @r%_find_config_filesz*BaseApplicationsManager._find_config_filess3 )MBB(````X````r'c $|||}|j|}|||||}dt jdtj ||d|dg}| | | ||||| dd}|r|d|z|t jdz| t!|d t j|}t%||d d dS) z Creates .htaccess file for application based on application config data :param str user_name: User's name :param str app_root: Application root :param doc_root: Document root for the domain :return: None z{} zPassengerAppRoot "{}" zPassengerBaseURI "/{}" app_uripassenger_log_fileNzPassengerAppLogFile "%s" r*r?r@rI)get_app_configr" get_homedirrJrR clpassengerHTACCESS_BEGINrvrwrTextend(get_interpreter_specific_passenger_linesget_binary_pathgetrO HTACCESS_ENDrrm_double_empty_linesr) r#rUapp_rootrW app_configuser_dirrZ new_linesrs r%update_htaccess_filez,BaseApplicationsManager.update_htaccess_files$((H== 9((3333IxS]^^ MM+4 5 5 % , ,RW\\(H-M-M N N & - -j.C D D FF  Hh ? ?    (^^,@$GG  P   9OPPPQQQ5i@@  y#>OPPPPPPr'ct)zu Return list of lines that needs to be added to htaccess and are specific to the interpreter )NotImplementedError) binary_pathrs r%rz@BaseApplicationsManager.get_interpreter_specific_passenger_liness "!r'c|||}||j}tj||j||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 Nbin)get_interpreter_version_for_app BINARY_NAMErvrwrTVENV_DIR)r#r8rr binary_nameversions r%rz'BaseApplicationsManager.get_binary_pathsG66tXFF  *Kw||HdmXw{[[[r'cp||jS||j|iS)z Retrives info about user(s). :param str | None username: Username to retrive information. :return: Dictionary with user info. Example: {'user1': pw_struct} )r" get_user_dictget_pw_by_name)r#rls r%get_users_dictz&BaseApplicationsManager.get_users_dicts9  9**,, ,$)228<<==r'c*i}||}tj|rtjdkrJ|j|}dt_tj ||j |j dd}nt|} tjd|pg}nA#t t"f$r-t%jd|jwxYw|S)z Get all data from user's config :param user: name of unix user :return: json data from user's config as dictionary rTF exit_on_error write_logrHzUser config "{}" is broken)_get_path_to_user_configrvrwisfilegeteuidr"rsecureio SILENT_FLAGread_file_securepw_uidpw_gidr jsonloadsrT ValueError TypeErrorr WrongDatarR _USER_CONFIG)r#r8_user_config_data user_configuser_pwdatas r%r6z,BaseApplicationsManager.get_user_config_datas 33D99  7>>+ & & gz||q  )22488'+$  0gngn?DPUWWW&k22 g$(Jrwwtzr/B/B$C$C!! * g g g$./K/R/RSWSd/e/efff g  s ()C>Dcr||} t|||S#t$rYdSwxYw)z Retrieves full application config :param user: User name :param app_dir: Application directory :return: Application data as dictionary If None - No application data found in config N)r6rrc)r#r8rduser_config_datas r%rz&BaseApplicationsManager.get_app_configsR 44T:: *4:JKK K   44 s ( 66c>|||}|dS)z Retrieves domain for provided user's application :param username: user name :param app_directory: application root directory :return str: application domain rhr)r#rlr9rs r%get_app_domainz&BaseApplicationsManager.get_app_domain s$((=AA (##r'c>|||}|dS)z Retrieves uri for provided user's application :param username: user name :param app_directory: application root directory :return str: application uri r~rr#rlr9r:s r% get_app_uriz#BaseApplicationsManager.get_app_uri*s$&&x?? ""r'c>|||}|dS)z Retrieves name of startup file for provided user's application :param username: user name :param app_directory: application root directory :return str: name of startup file of application startup_filerrs r%get_app_startup_filez,BaseApplicationsManager.get_app_startup_file4s$&&x??''r'c>|||}|dS)z Retrieves status for provided user's app_directory :param username: user name :param app_directory: application root directory :return str: status of application app_statusrrs r%get_app_statusz&BaseApplicationsManager.get_app_status>s$&&x?? %%r'c|||}|'tjd||d|jzS)z Retrieves interpreter version for provided user and application :param username: user name :param app_directory: application root directory :return str: major interpreter version Nz)Application config is missed for user: {} %s_version)rrConfigMissingErrorrR INTERPRETERrs r%rz7BaseApplicationsManager.get_interpreter_version_for_appHs]&&x??   35CCI6(CSCSUU U t'7788r'c|j|}tj||j}|S)z Get full path to user config ~/${_USER_CONFIG} :param username: name of unix user :return: full path to config )r"rrvrwrTr)r#rl user_homeapplication_configs r%rz0BaseApplicationsManager._get_path_to_user_configUs8 I))(33 W\\)T5FGG!!r'cT|jj|}||kr|SdS)z Retrieves full version for supplied major version. :return: str - Full version or None if full version not found N)r!pkgget_full_version)r# major_version full_versions r%_get_full_version_for_shortz3BaseApplicationsManager._get_full_version_for_short`s2 }(99-HH = ( ( tr'ct|j|vr|||jd|<dS|j||id}|||j<dS)a@ Add single application data to user_data_dest_dict :param users_data_dest_dict: Destination dictionary with application data :param user_pw_entry: User's passwd entry :param app_root_dir: Application root directory :param app_data: Application data :return: None applications)homedirrN)pw_namepw_dir)r#users_data_dest_dict user_pw_entry app_root_dirr: user_datas r%_add_single_user_appz,BaseApplicationsManager._add_single_user_appjsd  $8 8 8X` !6 7 G U U U)/!-x 8I;D !6 7 7 7r'c||j|}t|d|z}t||d<dS)z&> Y Y "L(h-- H1L1L'+'G'GQ\H]'^'^ $'/3KSf3f3f12JKKKIK#$<=gF !5!5!)<9M *"6",",&H\ " %,-EFwOJ  : :8\S` a a a  % %j-x X X X X7 Y Yr'cLt|D]\}}d|vrd|d<|||<|S)z Append absent 'passenger_log_file' key with None value to each application :param user_config_dict: Sourse dictionary to modify :return: Modified dict with 'passenger_log_file' keys rNr )user_config_dictrr:s r%_add_absent_passenger_log_filez6BaseApplicationsManager._add_absent_passenger_log_filesK#,,<"="= 2 2 Hh#83315-.)1 X & &r'cL|tj}tj||j}tj|st | |dkr&dt_tj |||dd}nt|}| tj d|S#ttt t"f$r'}t%d|t'|dd d}~wwxYw) a] Read [python|ruby|node]-selector.json file from user's directory. :param euid: current effective uid :param user_homedir: user's home directory :param uid: uid for drop rights :param gid: gid for drop rights :return: Cortege contents_dict. None - there is no [python|ruby|node]-selector.json file in user's directory :raises BaseSelectorError if error. Exception contents: {'message': "File %(file)s read/parse error: %(error)s", 'context': {'file': node_json_path, 'error': 'some message'}} NrTFrrHz)File %(file)s read/parse error: %(error)s)fileerror)messagecontext)rvrrwrTrrxrrrrr rrrr/r0rrrstr)r# user_homediruidgideuidjson_config_path file_lineses r%read_user_selector_config_jsonz6BaseApplicationsManager.read_user_selector_config_jsons+ <:<A AAc||} t|||}||d<n#t$rYdSwxYw|||dS)z Retrieves application status :param user: User name :param app_dir: Application directory :param new_status: New appication status :type new_status: str :return: None rN)r6rrcr7)r#r8rd new_statusrrs r%set_app_statusz&BaseApplicationsManager.set_app_statuss} 44T:: 0w@PQQJ'1J| $ $    FF  ((/?@@@@@s . <<c||}tjdkstjdkrt jdt |} tj||dddS#tttf$r-}t j |d |d}~wwxYw)z Write data to user's config :param user: name of unix user :param config_data: data in json format :return: None rz$root should not write to user configi_tmp)content dest_pathpermsuffixz%Could not write json user config ({})N)rrvrgetegidrSelectorExceptionrrwrite_file_via_tempfiler/r0rUnableToSaveDatarR)r#r8rer dumped_datars r%r7z3BaseApplicationsManager.write_full_user_config_datas 88>> :<<1    1 1 2688 8!+..  C  ,#*        ), C C C 1 7>>qAACC C Cs(BC(CCc|}t|D]\}} ||j|j|j}|<|D]'}|d|jz|krdS(k#t$rYwt$r,}| |j |j zYd}~d}~wwxYwdS)z Returns True if specified NodeJS version is in use by any app of any user. It will stop search on the first match. :param version: NodeJS interpreter major version :return True | False NrTF)rr rrrrvaluesrrrrr4rr)r#r user_inforUruser_apps_datarprs r%is_version_in_usez)BaseApplicationsManager.is_version_in_uses'')) (1)(<(< @ @ $I} @!%!D!D]EY[h[oEREY"["[!--4466((77<$2B#BCCwNN#'444O"   $ @ @ @((QY)>???????? @us$A B B C C$"C  Cc tjdkr*tjtjj} ||}n,#t jj$rtj |wxYw| }|d}t|D]\}} | |j|j|j}||||E#t$$rYQt&$r\}tjdkr9||j|jzd|jd|jd|d<n|Yd}~d}~wt2$r]}tjdkr:|d|jd |d |d|jd|jd|d<nYd}~d}~wwxYw|S) a Retrieves info about all installed NodeJS interpreters and user(s) applictions :param user: User name for read applictions. If None and current euid == 0 - all users will be processed. If current euid != 0 (called under some user), this argument will be ignored and only user with uid == euid will be processed :return: Dictionary with user(s) applications info :raises ClSelectExcept.NoSuchUser or BaseSelectorError ravailable_versionsz Some user's zD can't be read. Some user(s) data absent in output. Please see file z for detailswarningNzFailed to process z for user r))rvr_stdpwdgetpwuidrrrclpwdNoSuchUserExceptionr NoSuchUser_get_interpreter_infor rrrrrrrr4rrrr. Exception) r#r8rusers_apps_inforrUrrrs r%get_applications_users_infoz3BaseApplicationsManager.get_applications_users_info/sX& :<<1  #BJLL119D 2++D11II~1 2 2 2 +D11 1 24466,-AB)2)(<(<( (  $I}' !%!D!D]EY[h[oEREY"["['' 7I>ZZZZ"   $   :<<1$$,,QY-BCCCC372C2C2CTEXEXEX2ZOI.. G /....    :<<1$$,,, ---yyy!!=>>>> 372C2C2CTEXEXEX2ZOI.. /.... $s8A)B7=C55 G  G  AE!! G .AGG Tc|j|j}tj||j|}|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 ) r"rrrvrwrTrrxrr)r#rlrchk_env chk_app_rootrapp_venvs r%get_app_foldersz'BaseApplicationsManager.get_app_folderswsI,,X66= 7<< 4=(CC  327>>(33 3(22 27<< 844  0x 8 8 0%h// /!!r'c8|j}|S)z)Get initial information about interpreter)r! get_summary)r#rs r%rz-BaseApplicationsManager._get_interpreter_infos-3355r'c@|jj|S)zi Just a public proxy to internal method that blocks any actions with interpreter )r!racquire_interpreter_lock)r# it_versions r%r%z0BaseApplicationsManager.acquire_interpreter_locks } 99*EEEr')Fr )TT)-__name__ __module__ __qualname____doc__rr.rrrr& classmethodr4r<rarfrs staticmethodr|rrrrrr6rrrrrrrrrrrrrrJrr7rrr!rr%rCr'r%rr's L/NKHK  [  = = =---@$@@@@6aaa\a%Q%Q%QN""^\" \ \ \ \ > > > >!!!B   $$$###(((&&& 9 9 9 " " "DDD(666 $Y$Y$YL   \   ^ ^ ^ ^D AAA$CCC26FFFFP""""$ FFFFFr'r), __future__rrrrrvpwdrriabcrrrclselect.clpassengerrr future.utilsr past.builtinsr clcommonr clcommon.utilsr rclselect.utilsrrrclselectrclselect.baseclselectrrrrselector_managerrrrrrobjectrrCr'r%r:s'&&&&&%%%%%%  ''''''''******""""""!!!!!!;;;;;;;;OOOOOOOOOO###### 211111::::::::222222''''''l Fl Fl Fl Fl FnnWf==l Fl Fl Fl Fl Fr'