Viewing file: global_ini.py (4.93 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# -*- coding: utf-8 -*-
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2021 All Rights Reserved # # Licensed under CLOUD LINUX LICENSE AGREEMENT # http://cloudlinux.com/docs/LICENSE.TXT import logging import os import re import pwd from contextlib import suppress from glob import iglob from typing import Tuple from secureio import disable_quota
from xray.internal.utils import user_context
logger = logging.getLogger()
GLOBAL_INI_MARKER = '/opt/cloudlinux/flags/enabled-flags.d/xray-ini-global-mode.flag'
# directories that don't matter for us # php is either outdated or just internal _EXCLUDE_DIR_PATHS = ( 'php44', 'php51', 'php52', 'php53', 'php\d+-imunify', 'php-internal' )
# global set of ini locations where php # usually loads configuration files from # some of them may be missing, like /opt/plesk # which only exists on plesk _INI_LOCATIONS = ( '/opt/alt/php[0-9][0-9]/link/conf', '/opt/cpanel/ea-php[0-9][0-9]/root/etc/php.d', '/opt/plesk/php/[0-9].[0-9]/etc/php.d', '/usr/local/php[0-9][0-9]/lib/php.conf.d', '/usr/share/cagefs/.cpanel.multiphp/opt/cpanel/ea-php[0-9][0-9]/root/etc/php.d', '/usr/share/cagefs-skeleton/usr/local/php[0-9][0-9]/lib/php.conf.d' )
# same as above, but ini which are writeable by users _INI_USER_LOCATIONS = ( dict(path='/var/cagefs/*/*/etc/cl.php.d/alt-php[0-9][0-9]', user=lambda path: pwd.getpwnam(path.split('/')[4])), )
def _is_excluded_path(dir_path: str) -> list: """ Check if given path is in exclude list. """ res = [substring for substring in _EXCLUDE_DIR_PATHS if re.search(substring, dir_path)] return res
def _iter_existing_ini_locations() -> Tuple[Tuple[int, int], str]: """ Generator of existing paths (matching known wildcard locations) for additional ini files Returns tuple of (uid, gid) and path. """ for location in _INI_LOCATIONS: for dir_path in iglob(location): if _is_excluded_path(dir_path): continue yield (0, 0), dir_path
for location in _INI_USER_LOCATIONS: for dir_path in iglob(location['path']): if _is_excluded_path(dir_path): continue
try: pw_record = location['user'](dir_path) except: logger.info('Unable to get information about user ' 'owning %s directory (maybe he`s already terminated?), ' 'skip updating', dir_path) continue else: yield (pw_record.pw_uid, pw_record.pw_gid), dir_path
def _create_single_ini(uid: int, gid: int, ini_path: str): # write counter of tasks so during mode switch # we can still safely cleanup ini files not # bound to any exiting tasks ini_content = ';xray.tasks=0\nextension=xray.so'
path = os.path.join(ini_path, 'xray.ini') if os.path.exists(path): return
with user_context(uid, gid), \ disable_quota(), \ open(path, 'w') as ini: logger.info('Generating %s file...', path) ini.write(ini_content)
def is_global_ini_mode(): return os.path.exists(GLOBAL_INI_MARKER)
def create_global_ini_mode_marker(): open(GLOBAL_INI_MARKER, 'w').close()
def remove_global_ini_mode_marker(): with suppress(FileNotFoundError): os.remove(GLOBAL_INI_MARKER)
def create_ini_files() -> None: """ Place xray.ini into each existing Additional ini path, including cagefs ones. """ logger.info('Generating xray.ini files...') for (uid, gid), ini_path in _iter_existing_ini_locations(): try: _create_single_ini(uid, gid, ini_path) except PermissionError: logger.warning('Unable to update file %s, ' 'possible permission misconfiguration', ini_path) continue except Exception as e: logger.warning('Unexpected error happened during file processing: ' '"%s", error: "%s"', ini_path, str(e), exc_info=True) continue logger.info('Finished!')
def remove_ini_files() -> None: """ Remove all gathered clos_ssa.ini files """ logger.info('Removing clos_ssa.ini files...') for (uid, gid), clos_ini_dir in _iter_existing_ini_locations(): ini_file = os.path.join(clos_ini_dir, 'xray.ini') try: with user_context(uid, gid), open(ini_file) as f: contents = f.read()
# unlink file only if there are no linked tasks # case with minus sign covers negative values if "xray.tasks=0" in contents or \ "xray.tasks=-" in contents: os.unlink(ini_file) except FileNotFoundError: continue except Exception as e: logger.warning('Unable to remove file: "%s", error: "%s"', ini_file, str(e)) continue
logger.info('Finished!')
|