????
Current Path : /proc/324102/root/usr/bin/ |
Current File : //proc/324102/root/usr/bin/isppackagesreducer |
#!/opt/cloudlinux/venv/bin/python3 -bb # -*- coding: utf-8 -*- # cloudlinux-license Utility to erase package limits in /etc/container/ve.cfg # for ISPManager5 panels # # Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2021 All Rights Reserved # # Licensed under CLOUD LINUX LICENSE AGREEMENT # http://cloudlinux.com/docs/LICENCE.TXT from __future__ import absolute_import from __future__ import print_function from __future__ import division import sys import subprocess import simplejson as json from future.utils import iteritems import cldetectlib as detect from copy import deepcopy from clcommon import ClPwd from collections import defaultdict from cllimits.lib import exec_utility from clcontrollib import ISPManagerGetPackagesException from lvectllib import get_XML_cfg, get_globals, check_value import lvectllib import xml.dom.minidom as xml import time UTILITY_PATH = "/usr/sbin/lvectl" def check_if_isp5_master(): if detect.getCP() and detect.is_ispmanager(): return detect.ispmanager5_is_master() print("Either this server hasn't ControlPanel or that ControlPanel isn't ISPManager5") sys.exit(1) def get_user_packages_dict(): """ Is copy-pasted from clcontrollib.py source code before it was replaced with LU-256. Returns dict of {'uid': 'package_name'} """ clpwd = ClPwd() dict_uid_package = {} if check_if_isp5_master(): # ISP5 master try: # Get users list # Call mgrctl: /usr/local/mgr5/sbin/mgrctl -m ispmgr user -o json p = subprocess.Popen(['/usr/local/mgr5/sbin/mgrctl', '-m', 'ispmgr', 'user', '-o', 'json'], stdout=subprocess.PIPE) out, _ = p.communicate() except OSError as e: raise ISPManagerGetPackagesException("ERROR: Can't execute /usr/local/mgr5/sbin/mgrctl: %s" % str(e)) try: mgrctl_out = json.loads(out) except ValueError: raise ISPManagerGetPackagesException("ERROR: mgrctl invalid output:\n%s" % out) if 'doc' not in mgrctl_out or 'elem' not in mgrctl_out['doc']: print("ControlPanel has no users, maybe current license is outdated") sys.exit(1) users_data = mgrctl_out['doc']['elem'] for user_data in users_data: try: # determine user location user_location = user_data['loc']['$'] # user_location example: 'localhost (95.164.68.74)' # We don't support non-local users if not user_location.startswith('localhost'): continue # determine uid user_name = user_data['name']['$'] uid = clpwd.get_uid(user_name) # determine package package_data = user_data['preset'] if '$orig' in package_data: # non-package user package_name = package_data['$orig'].replace('#', '') else: # Package user package_name = package_data['$'] # Add uid-package to dictionary dict_uid_package[uid] = package_name except IndexError: # Ignore record, if any index absent continue else: # ISP5 node try: # Get users list # Call mgrctl: /usr/local/mgr5/sbin/mgrctl -m ispmgrnode user # JSON output not supported on node, use TEXT output p = subprocess.Popen(['/usr/local/mgr5/sbin/mgrctl', '-m', 'ispmgrnode', 'user'], stdout=subprocess.PIPE) out, _ = p.communicate() except (OSError, ) as e: raise ISPManagerGetPackagesException("ERROR: Can't execute /usr/local/mgr5/sbin/mgrctl: %s" % str(e)) # Parse output users_data = out.split('\n') for user_data in users_data: if not user_data: continue user_name = None try: # user parametres # user_params_list example: # ['name=bogdan1', 'fullname=', 'active=on', 'quota_total=0', 'quota_used=0', # 'limit_cpu=', 'limit_db=', 'limit_db_users=', 'limit_dirindex=index.html', 'index.php', # 'limit_emaildomains=', 'limit_emails=', 'limit_ftp_users=', 'limit_mailrate=', # 'limit_maxclientsvhost=', 'limit_memory=', 'limit_mysql_maxconn=', # 'limit_mysql_maxuserconn=', 'limit_mysql_query=', 'limit_mysql_update=', # 'limit_nginxlimitconn=', 'limit_php=', 'limit_process=', 'limit_webdomains='] user_params_list = user_data.split(' ') # print user_params_list for user_param in user_params_list: if user_param.startswith('name'): # username found user_name = user_param.split('=')[1] break except IndexError: # Ignore record, if any index absent pass # determine uid of user uid = clpwd.get_uid(user_name) # Add uid to dictionary. # Package name unavailable on ISP5 node, so create it manually by agreement with ISP Manager support dict_uid_package[uid] = "package_%s" % str(uid) return dict_uid_package def construct_args(package_data, user_data): """ Generates list of lvectl arguments to set limits :param dict package_data: Limits for given package as "limit_name": "limit_value" :param set user_data: Limits that user already has and we don't want to change :return: List of strings """ res = [] for key, value in iteritems(package_data): if key not in user_data: res.append("--%s=%s" % (key, value)) return res # Save XML config ve.cfg.timestamp def save_ve_config_backup(XML): XML = XML.toprettyxml(encoding='utf-8',indent='', newl='') XML = XML.replace("\n",'').replace("\t",'') new_xml = xml.parseString(XML) ve_cfg_backup_name = '/etc/container/ve.cfg.' + str(int(time.time())) f = open(ve_cfg_backup_name, "wb") f.write(new_xml.toprettyxml(encoding='utf-8')) f.close() def main(): lvectllib.get_global_lock(True) get_XML_cfg() # lvectllib uses global variables, so we have to get their values global_vars = get_globals() ve_defaults = global_vars['ve_defaults'] # If we have no packages' limits in /etc/container/ve.cfg if len(global_vars['ve_package']) == 0: print("Here isn't any package. No changes needed") return # Create backup for ve.cfg save_ve_config_backup(global_vars['ve_cfg']) # Get list of users and their packages from mgrctl utility dict_uid_package = get_user_packages_dict() # Group uids by package names packages_uids = defaultdict(list) for uid, package in dict_uid_package.items(): packages_uids[package].append(uid) packages = {} to_delete = {} # For every package, get it's limits and put that to packages dict # store packages' names that exist in /etc/container/ve.cfg into to_delete dict for el in global_vars['ve_package']: pack_id = el.getAttribute('id') setup_data = {} if el.getAttribute('reseller'): to_delete[pack_id] = "--reseller=%s" % el.getAttribute('reseller') else: to_delete[pack_id] = '' if pack_id in list(packages_uids.keys()): check_value('ncpu', el, ve_defaults, setup_data) try: cpu = el.getElementsByTagName('cpu')[0].getAttribute('limit') if cpu.endswith("%") or cpu.endswith("mhz") or cpu.endswith("ghz"): setup_data['speed'] = cpu else: setup_data['cpu'] = cpu except (ValueError, IndexError, TypeError): pass check_value('io', el, ve_defaults, setup_data) check_value('mem', el, ve_defaults, setup_data) # mem limit is in 4K bloks, convert it to M if setup_data.get('mem', False): setup_data['mem'] = str(int(setup_data['mem'])*4//1024) + 'M' try: ep = int(el.getElementsByTagName('other')[0].getAttribute('maxentryprocs')) setup_data['ep'] = ep except (ValueError, IndexError, TypeError): pass check_value('nproc', el, ve_defaults, setup_data) check_value('pmem', el, ve_defaults, setup_data) # pmem limit is in 4K bloks, convert it to M if setup_data.get('pmem', False): setup_data['pmem'] = str(int(setup_data['pmem'])*4//1024) + 'M' check_value('iops', el, ve_defaults, setup_data) packages[pack_id] = deepcopy(setup_data) users = defaultdict(set) for el in global_vars['ve_lve']: user_set = set(['vmem',]) for child in el.childNodes: if child.nodeType == child.ELEMENT_NODE: if child.nodeName == 'other': user_set.update(['ep', 'maxEntryProcs']) elif child.nodeName == 'cpu': user_set.update(['cpu', 'speed']) elif child.nodeName == 'mem': user_set.add('mem') else: user_set.add(child.nodeName) users[str(el.getAttribute('id'))].update(user_set) for uid, package in dict_uid_package.items(): package_data = packages.get(package) if package_data is not None: # Call lvectl set uid --limit=value --limit=value to set limits from package to lve user limits = construct_args(package_data, users[str(uid)]) if len(limits) > 0: exec_utility(UTILITY_PATH, ["set", str(uid)] + limits) for package, reseller in to_delete.items(): # Call lvectl package-delete package_name to delete package limits from /etc/container/ve.cfg exec_utility(UTILITY_PATH, ["package-delete", package, reseller]) if __name__ == "__main__": main()