晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。 林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。 见渔人,乃大惊,问所从来。具答之。便要还家,设酒杀鸡作食。村中闻有此人,咸来问讯。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”(间隔 一作:隔绝) 既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。 南阳刘子骥,高尚士也,闻之,欣然规往。未果,寻病终。后遂无问津者。
| DIR:/opt/cloudlinux/venv/lib64/python3.11/site-packages/clsummary/ |
| Current File : //opt/cloudlinux/venv/lib64/python3.11/site-packages/clsummary/utils.py |
# coding=utf-8
#
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2019 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT
import configparser
import io
import os
import json
import fcntl
import struct
import time
from typing import Optional, Dict, AnyStr, Union
from jwt import decode, exceptions
from clcommon.lib.consts import DEFAULT_JWT_ES_TOKEN_PATH
from clcommon.lib.whmapi_lib import WhmApiRequest, WhmApiError
from clcommon.clcaptain import mkdir as mkdir_p
from clcommon.utils import process_is_running
from clconfig.cagefs_statistics_config import check_cagefs_initialized
from cldetectlib import CL_CONFIG_FILE
from secureio import write_file_via_tempfile
def dummy_none_function(*a, **kw):
return None
try:
from clselect.clselectctl import interpreter_versions_short_summary
from clselector.clpassenger_detectlib import is_clpassenger_active
except ImportError:
interpreter_versions_short_summary = dummy_none_function
is_clpassenger_active = dummy_none_function
_CL_STATISTICS_SECTION = "license_check"
_CL_STATISTICS_COLLECT_STATE_OPTION = "cl_statistics_enabled"
_CL_STATISTICS_COLLECT_RPM_STATE_OPTION = "cl_statistics_rpm_enabled"
_CL_STATISTICS_DIR = '/var/lve'
_CL_STATISTICS_SEND_STATUS_FILE = os.path.join(_CL_STATISTICS_DIR, 'summary_status.json')
_CL_STATISTICS_LOCK_PATH = '/var/run/cloudlinux_summary.send.lock'
_CL_STATISTICS_LOCK_FILE = None
CL_PLUS_SENDER_FILE_PATH = '/usr/share/cloudlinux/cl_plus/clplus_sender.py'
ALT_PYTHON_VIRTUALENV_BIN = '/opt/cloudlinux/venv/bin/virtualenv'
class SummaryStatus:
"""
Status of both, collecting and sending statistics
If process still collects statistics -> IN_PROGRESS
If statistics collected and sent correctly -> SUCCESS
If any error during collecting or sending -> FAILED
"""
SUCCESS = 'success'
IN_PROGRESS = 'in_progress'
FAILED = 'failed'
def is_virtualenv_installed():
"""
Checks is virtualenv installed
:return: True/False - installed or not
"""
return os.path.exists(ALT_PYTHON_VIRTUALENV_BIN)
def is_locked(lock_file):
"""
Check if file is locked by another process without acquiring lock.
IMPORTANT! This function should NOT be used to check lock acquired by the
same process that executes the is_locked() function. For example, when
process executes fcntl.lockf(LOCK_FILE), and then the same process executes
is_locked(LOCK_FILE), the is_locked(LOCK_FILE) call returns False.
Use is_locked() function to check lock acquired by another process only.
:param lock_file: file to check lock on
:type lock_file: file object or descriptor
"""
lock_data = struct.pack("hhllhh", fcntl.F_WRLCK, 0, 0, 0, 0, 0)
try:
lock_query = fcntl.fcntl(lock_file, fcntl.F_GETLK, lock_data)
lock_status = struct.unpack("hhllhh", lock_query)[0]
except (OSError, IOError):
# should never happen
return False
return lock_status != fcntl.F_UNLCK
def is_sending_process_running(acquire_lock=False):
"""
Check if processes collecting stats are running already (with --send option in command line)
:param acquire_lock: True = acquire lock when possible
:type acquire_lock: bool
:return bool: True = Processes are running
"""
global _CL_STATISTICS_LOCK_FILE
_CL_STATISTICS_LOCK_FILE = open( # pylint: disable=consider-using-with
_CL_STATISTICS_LOCK_PATH, 'w', encoding='utf-8'
)
if not acquire_lock:
return is_locked(_CL_STATISTICS_LOCK_FILE)
try:
fcntl.lockf(_CL_STATISTICS_LOCK_FILE, fcntl.LOCK_EX | fcntl.LOCK_NB)
except (OSError, IOError):
return True
return False
def _get_config():
"""
Retrieves ConfigParser object for /etc/sysconfig/cloudlinux file
:return:
"""
config = configparser.ConfigParser(interpolation=None,
strict=True)
config.optionxform = str # make config case sensitive
config.read(CL_CONFIG_FILE)
return config
def _write_config(config):
"""
write config to /etc/sysconfig/cloudlinux file
:param config: configParser object to write
return boolean: True|False
"""
try:
string_fp = io.StringIO()
config.write(string_fp)
content = string_fp.getvalue()
write_file_via_tempfile(content, CL_CONFIG_FILE, 0o644, prefix='cloudlinux_')
except (OSError, IOError):
return False
return True
def _get_config_value(parameter: str, default: bool = True) -> bool:
"""
Retrieves parameter's value from /etc/sysconfig/cloudlinux file, _CL_STATISTICS_SECTION section
"""
config = _get_config()
res = default
try:
res = config.getboolean(_CL_STATISTICS_SECTION, parameter)
except (configparser.NoSectionError, configparser.NoOptionError, ValueError):
# Treat absent/missing value as default
pass
return res
def _set_config_value(parameter: str, value: bool) -> None:
"""
Sets parameter's value to /etc/sysconfig/cloudlinux file, _CL_STATISTICS_SECTION section
"""
config = _get_config()
config.set(_CL_STATISTICS_SECTION, parameter, str(int(value)))
_write_config(config)
def is_statistic_enabled() -> bool:
"""
Retrieves statistic collection status from /etc/sysconfig/cloudlinux file
:return: True/False - enabled/disabled
"""
return _get_config_value(_CL_STATISTICS_COLLECT_STATE_OPTION)
def is_statistic_rpm_enabled() -> bool:
"""
Retrieves rpm statistic collection status from /etc/sysconfig/cloudlinux file
:return: True/False - enabled/disabled
"""
return _get_config_value(_CL_STATISTICS_COLLECT_RPM_STATE_OPTION)
def set_statistic_collection_enabled(is_enabled: bool) -> None:
"""
Set statistic collection status to /etc/sysconfig/cloudlinux file
:param is_enabled: True/False - enabled/disabled
"""
_set_config_value(_CL_STATISTICS_COLLECT_STATE_OPTION, is_enabled)
def set_statistic_rpm_collection_enabled(is_enabled: bool) -> None:
"""
Set rpm statistic collection status to /etc/sysconfig/cloudlinux file
:param is_enabled: True/False - enabled/disabled
"""
_set_config_value(_CL_STATISTICS_COLLECT_RPM_STATE_OPTION, is_enabled)
def write_statistics_send_status_to_file(status_dict):
"""
Writes statistics send status to file /var/lve/summary_status.json
:param status_dict: status dictionary for write to file
:return:
"""
try:
if not os.path.exists(_CL_STATISTICS_DIR):
mkdir_p(_CL_STATISTICS_DIR)
content = json.dumps(status_dict)
# Write to file readable only for root
write_file_via_tempfile(content, _CL_STATISTICS_SEND_STATUS_FILE, 0o600, prefix='cloudlinux_')
except (OSError, IOError):
pass
def get_statistics_send_status_from_file():
"""
Retrieves statistics send status from file /var/lve/summary_status.json
:return: Dictionary with last send status. None if any error
"""
status_dict = None
try:
with open(_CL_STATISTICS_SEND_STATUS_FILE, encoding='utf-8') as f:
s_content = f.read()
status_dict = json.loads(s_content)
if status_dict['result'] == SummaryStatus.IN_PROGRESS \
and not is_sending_process_running():
# something went wrong during collection
status_dict['result'] = SummaryStatus.FAILED
status_dict['reason'] = 'Collecting statistics was failed. Error ' \
'report has been sent to developers and will be fixed soon'
except (OSError, IOError, ValueError, AttributeError, TypeError):
pass
return status_dict
def installed_interpreters_list(interpreter):
"""
Returns list of installed interpreters
:param interpreter: str - name of interpreter
:rtype: List of InterpreterSummary
"""
return [i for i in interpreter_versions_short_summary(interpreter) if i.installed]
def is_python_selector_installed():
"""
Checks that python selector is installed
Installed if:
- ea-apache24-mod-alt-passenger or alt-mod-passenger is installed
- alt-python-virtualenv is installed
:rtype: bool
"""
return is_clpassenger_active() and is_virtualenv_installed()
def is_ruby_selector_installed():
"""
Checks that ruby selector is installed
Installed if:
- ea-apache24-mod-alt-passenger or alt-mod-passenger is installed
- alt-python-virtualenv is installed
:rtype: bool
"""
return is_clpassenger_active() and is_virtualenv_installed()
def is_nodejs_selector_installed():
"""
Checks that nodejs selector is installed
Installed if:
- ea-apache24-mod-alt-passenger or alt-mod-passenger is installed
- At least one version is installed
:rtype: bool
"""
return is_clpassenger_active() and bool(installed_interpreters_list('nodejs'))
def is_php_selector_installed():
"""
Checks that php selector is installed
Installed if:
- CageFS is initialized
:rtype: bool
"""
return bool(check_cagefs_initialized())
def get_packages_with_lve_extensions():
"""
Gets packages with set lve limits via extension
"""
try:
result = WhmApiRequest('listpkgs').call()
except WhmApiError:
return []
lve_extensions_packages = [item['name'] for item in result['pkg']
if '_PACKAGE_EXTENSIONS' in item and item['_PACKAGE_EXTENSIONS'] == 'lve']
return lve_extensions_packages
def get_client_data_from_jwt_token(check_expiration=True) -> Optional[Dict[AnyStr, Union[AnyStr, bool]]]:
"""
Gets (if any) fields cl_plus and client_id from jwt token
:return: decoded jwt_token value, None if error
jwt_token: result of the successful decoding
"""
try:
with open(DEFAULT_JWT_ES_TOKEN_PATH, mode='rb') as file:
file_content = file.read().strip()
except (OSError, IOError):
return None
# JWT read success
try:
jwt_token = decode(file_content, algorithms=['HS256'],
options={'require_exp': True,
"verify_exp": check_expiration,
"verify_iss": True,
'verify_signature': False},
issuer='CloudLinux')
return jwt_token
# JWT format error
except exceptions.PyJWTError:
return None
def is_active_cloudlinux_license(token_data):
"""
Checks whether license ts is expired
"""
if not token_data:
return None
if not token_data.get('exp'):
return None
return int(time.time()) < int(token_data.get('exp'))
def get_cl_plus_sender_status() -> Optional[AnyStr]:
"""
Retrieves data from status of cl_plus_sender service
:return: status of service, Optional[AnyStr]
- 'active'
- 'inactive'
"""
try:
result = process_is_running(CL_PLUS_SENDER_FILE_PATH, False)
except FileNotFoundError:
result = False
return 'active' if result else 'inactive'
|