[
MAINHACK
]
Mail Test
BC
Config Scan
HOME
Create...
New File
New Folder
Viewing / Editing File: abstract_feature.py
File is not writable. Editing disabled.
import glob import logging import os from abc import ABCMeta, abstractmethod from math import isclose from typing import List import psutil logger = logging.getLogger(__name__) class FeatureStatus: ERROR = 'error' INSTALLED = 'installed' INSTALLING = 'installing' REMOVING = 'removing' NOT_INSTALLED = 'not_installed' MANAGED_BY_LVE = 'managed_by_lve' NOT_SUPPORTED_BY_CL_SOLO = "not-supported-by-cl-solo" def ea4_only(func): """ If Easy Apache 4 not installed, then raising an error :raises FeatureError :param func: install or remove func :return func: """ async def wrapper(*args, **kwargs): if not os.path.isfile('/etc/cpanel/ea4/is_ea4'): raise FeatureError( 'Hardened PHP is compatible only with Easy Apache 4!') return await func(*args, **kwargs) return wrapper class FeatureError(Exception): """Feature operation can't be performed error""" pass class FeatureNotice(FeatureError): """Feature operation can't be performed notice""" pass class AbstractFeature(metaclass=ABCMeta): NAME = "AbstractFeature" INSTALL_LOG_FILE_MASK = None # type: str REMOVE_LOG_FILE_MASK = None # type: str _CMD_LIST = [] # type: List[str] def __init__(self, sink=None): assert self.INSTALL_LOG_FILE_MASK, "variable isn't set!" assert self.REMOVE_LOG_FILE_MASK, "variable isn't set!" self._sink = sink async def init(self): self.is_installed = await self.check_installed() return self @property def installation_live_log(self): return self._get_live_log(self.INSTALL_LOG_FILE_MASK) @property def removal_live_log(self): return self._get_live_log(self.REMOVE_LOG_FILE_MASK) @classmethod def _log_still_used(cls, log_file): """Checks if any processes are using log file.""" try: with open(log_file + ".pid") as pf: pid, creation_time = pf.read().strip().split() return isclose( psutil.Process(int(pid)).create_time(), float.fromhex(creation_time), rel_tol=1e-12 ) except (OSError, ValueError, psutil.NoSuchProcess): return False @staticmethod def _ls_logs(log_mask): """ :param str log_mask: regexp of log file path :return: list of files found by log_mask """ return glob.glob(log_mask) @classmethod def _get_live_log(cls, file_mask): """ Returns path of log file, which used by some process. If log file used by process, assuming that installation/removal is in the progress :param str file_mask: regexp of log file path :return: str path of log, used by some process """ return next(filter(cls._log_still_used, cls._ls_logs(file_mask)), None) async def check_installed(self) -> bool: if self.installation_live_log: return False if self.removal_live_log: return True return await self._check_installed_impl() @abstractmethod async def _check_installed_impl(self) -> bool: return False @abstractmethod async def install(self) -> str: """ :return str: path to log file with installation process :raise FeatureError: when feature is already installed, concurrent operation is in progress, feature is not applicable for given setup, etc. """ raise NotImplementedError() @abstractmethod async def remove(self) -> str: raise NotImplementedError() @staticmethod def raise_if_shouldnt_install_now(func): """ Checks before operation if similar or mutually exclusive operation is in the progress. Checks if there are condition why operation can't be performed. :raises FeatureError: if operation couldn't be performed :returns str msg: log path if already ongoing operation :returns continue function isntall/remove: if operation is permitted """ async def wrapper(self): # check if the operation is in progress if self.removal_live_log: raise FeatureError('Wait until uninstalling is finished!') elif self.is_installed: raise FeatureNotice("{} is already installed" .format(self.NAME)) return self.installation_live_log or await func(self) return wrapper @staticmethod def raise_if_shouldnt_remove_now(func): """ :raises FeatureError: if operation couldn't be performed :returns str msg: log path if already ongoing operation :returns continue function isntall/remove: if operation is permitted """ async def wrapper(self): # check if the operation is in progress if self.installation_live_log: raise FeatureError('Wait until installation is finished!') elif not self.is_installed: raise FeatureNotice("Can't delete {}, because it's " "not installed".format(self.NAME)) return self.removal_live_log or await func(self) return wrapper async def status(self): if self.installation_live_log: msg = '{} is installing'.format(self.NAME) status = FeatureStatus.INSTALLING elif self.removal_live_log: msg = '{} is removing'.format(self.NAME) status = FeatureStatus.REMOVING elif await self.check_installed(): msg = '{} is installed'.format(self.NAME) status = FeatureStatus.INSTALLED else: msg = '{} is not installed'.format(self.NAME) status = FeatureStatus.NOT_INSTALLED return { 'items': { 'message': msg, 'status': status, } }
Save Changes
Cancel / Back
Close ×
Server Info
Hostname: server05.hostinghome.co.in
Server IP: 192.168.74.40
PHP Version: 7.4.33
Server Software: Apache
System: Linux server05.hostinghome.co.in 3.10.0-962.3.2.lve1.5.81.el7.x86_64 #1 SMP Wed May 31 10:36:47 UTC 2023 x86_64
HDD Total: 1.95 TB
HDD Free: 691.34 GB
Domains on IP: N/A (Requires external lookup)
System Features
Safe Mode:
Off
disable_functions:
None
allow_url_fopen:
On
allow_url_include:
Off
magic_quotes_gpc:
Off
register_globals:
Off
open_basedir:
None
cURL:
Enabled
ZipArchive:
Disabled
MySQLi:
Enabled
PDO:
Enabled
wget:
Yes
curl (cmd):
Yes
perl:
Yes
python:
Yes
gcc:
Yes
pkexec:
No
git:
Yes
User Info
Username: itsweb
User ID (UID): 1619
Group ID (GID): 1621
Script Owner UID: 1619
Current Dir Owner: N/A