View file File name : packages.py Content :#coding:utf-8 # Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2022 All Rights Reserved # # Licensed under CLOUD LINUX LICENSE AGREEMENT # http://cloudlinux.com/docs/LICENSE.TXT from __future__ import print_function from __future__ import division from __future__ import absolute_import import os import clcommon import lvectllib from clcommon.clconfpars import load_fast from cllimits.clquota_lib import ClQuotaLib from clcommon.cpapi import resellers, is_panel_feature_supported, Feature from clcommon.lib import MySQLGovernor PKG_DIR = "/var/cpanel/packages" LVE_CONFIG = "/etc/container/ve.cfg" QUOTA_CONFIG = "/etc/container/cl-quotas.dat" MYSQLGOV_PACKAGES_CONFIG = "/etc/container/governor_package_limit.json" LIMITS_NAMES = ( ('inodes_soft', 'INODES soft'), ('inodes_hard', 'INODES hard'), ) LVE_LIMITS_NAMES = ( ('ncpu', 'NCPU'), ('cpu', 'SPEED'), ('io', 'IO'), ('mem', 'Vmem'), ('pmem', 'Pmem'), ('nproc', 'NPROC'), ('iops', 'IOPS'), ('ep', 'Max Entry Procs'), ) GOVERNOR_LIMITS_NAMES = ( ('mysql_cpu', 'MySQL CPU'), ('mysql_io', 'MySQL IO'), ) def is_reseller_package(package): reseller_list = resellers() for reseller in reseller_list: if package.startswith(reseller + '_'): return True return False def check_data(data, name, def_value): if data is None: if name == "CPU": def_value = f"{def_value // 100}%" # convert kernel version speed limit to human readable format data = def_value return data def _get_limit_defaults(): limit_defaults = {'inodes_soft': 0, 'inodes_hard': 0} if is_panel_feature_supported(Feature.LVE): limit_defaults |= lvectllib.ve_defaults.copy() if is_panel_feature_supported(Feature.GOVERNOR): limit_defaults |= {'mysql_cpu': 0, 'mysql_io': 0} return limit_defaults def _get_limit_names(): limit_names = LIMITS_NAMES if is_panel_feature_supported(Feature.LVE): limit_names += LVE_LIMITS_NAMES if is_panel_feature_supported(Feature.GOVERNOR): limit_names += GOVERNOR_LIMITS_NAMES return limit_names def _handle_limit(limit_name, limit_value, message, limit_defaults): if limit_name == 'cpu': limit_value = clcommon.validate_cpu(limit_value) limit_value = check_data(limit_value, message, f"{limit_defaults[limit_name] // 100}%") elif limit_name in ('pmem', 'mem', 'vmem'): limit_value = clcommon.memory_to_page(limit_value, 0) limit_value = check_data(limit_value, message, limit_defaults[limit_name]) elif limit_name in ('inodes_soft', 'inodes_hard', 'mysql_io'): limit_value = clcommon.validate_int(limit_value, min_val=-1) limit_value = check_data(limit_value, message, limit_defaults[limit_name]) elif limit_name == 'mysql_cpu': limit_value = limit_value.replace('%', '') limit_value = clcommon.validate_int(limit_value, min_val=-1) limit_value = check_data(limit_value, message, limit_defaults[limit_name]) else: limit_value = clcommon.validate_int(limit_value) limit_value = check_data(limit_value, message, limit_defaults[limit_name]) return limit_value def _categorize_limits(limit_name, limit_value, lve_data, governor_limits, quota_data): if limit_name in ('ncpu', 'cpu', 'io', 'mem', 'pmem', 'nproc', 'iops', 'ep'): lve_data[limit_name] = limit_value elif limit_name in ('mysql_cpu', 'mysql_io'): governor_limits[limit_name] = limit_value else: quota_data[limit_name] = limit_value def _update_lve_limits(lve_data): if is_panel_feature_supported(Feature.LVE): lvectllib.package_set(lve_data) def _update_quota_data(package, quota_data): if quota_data: ClQuotaLib().set_package_limits_independently(package, quota_data) os.utime(LVE_CONFIG) elif os.path.exists(QUOTA_CONFIG): os.utime(QUOTA_CONFIG) def _update_governor_limits(package, governor_limits): if not is_panel_feature_supported(Feature.GOVERNOR): return governor_lib = MySQLGovernor() if not governor_lib.is_governor_present(): return governor_lib.set_package_limits( package, int(governor_limits['mysql_cpu']), int(governor_limits['mysql_io']), ) if os.path.exists(MYSQLGOV_PACKAGES_CONFIG): os.utime(MYSQLGOV_PACKAGES_CONFIG) def save_package(package): """ Save cpanel package info to LVE config and cl-quotas.dat """ package_path = os.path.join(PKG_DIR, package) if not os.path.isfile(package_path): return None if is_reseller_package(package): return None # we skip all resellers packages package_params = load_fast(package_path) extention_list = package_params.get('_PACKAGE_EXTENSIONS', '').split() if "lve" not in extention_list: # skip packages without lve extention return None lve_data = {'ve_id': package, 'save': True} quota_data = {} governor_limits = {'mysql_cpu': None, 'mysql_io': None} limit_names = _get_limit_names() limit_defaults = _get_limit_defaults() for limit_name, message in limit_names: limit_value = package_params.get(f'lve_{limit_name}', '') if limit_name in governor_limits and limit_value == 'DEFAULT': governor_limits[limit_name] = 0 if limit_value == 'DEFAULT': continue limit_value = _handle_limit(limit_name, limit_value, message, limit_defaults) _categorize_limits(limit_name, limit_value, lve_data, governor_limits, quota_data) _update_lve_limits(lve_data) _update_quota_data(package, quota_data) _update_governor_limits(package, governor_limits) return True