Mini Shell
#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
Zerion Mini Shell 1.0