%PDF- %PDF-
| Direktori : /usr/share/l.v.e-manager/cpanel/stats_bar/ |
| Current File : //usr/share/l.v.e-manager/cpanel/stats_bar/get_lve_limits.py |
#!/opt/cloudlinux/venv/bin/python3 -sbb
# -*- 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
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
import json
import sys
import os
import errno
from cldetectlib import get_param_from_file
from clcommon.utils import exec_utility, get_file_lines
from clcommon.ui_config import UIConfig
LVE_INFO = '/var/lve/info'
PERCENTS_STATS_MODE_FLAG = '/opt/cloudlinux/flags/enabled-flags.d/percentage-user-stats-mode.flag'
# Format of line in /var/lve/info (formed by lvestats-server):
# (id, mep, lep, cpu_usage, lcpu, mem_usage, lmem,
# mem_fault, mep_fault, lmemphy, memphy, memphy_fault,
# lnproc, nproc, nproc_fault, lcpuw, ioread, iowrite)
ID_INDEX = 0
EP_INDEX = 1
LEP_INDEX = 2
CPU_INDEX = 3
LCPU_INDEX = 4
MEM_INDEX = 5
LMEM_INDEX = 6
MEMF_INDEX = 7
MEPF_INDEX = 8
LPMEM_INDEX = 9
PMEM_INDEX = 10
PMEMF_INDEX = 11
LNPROC_INDEX = 12
NPROC_INDEX = 13
NPROCF_INDEX = 14
LCPUW_INDEX = 15
IO_INDEX = 16
LIO_INDEX = 17
LIOPS_INDEX = 18
IOPS_INDEX = 19
MEMORY_PAGE_SIZE = 4096
BYTES_IN_KILO = 1024
LIMITS_LIST = [
('lcpu', 'cpu'),
('lep', 'ep'),
('lmem','mem'),
('lmemphy', 'memphy'),
('liops', 'iops'),
('lio','io'),
('lnproc', 'nproc'),
('linodes', 'inodes'),
]
template_dict = {
'cpu' : {
'id' : 'lvecpu',
'description' : 'CPU Usage',
'formatter' : None,
},
'ep': {
'id':'lveep',
'description' : 'Entry Processes',
'formatter' : None,
},
'mem': {
'id':'lvemem',
'description' : 'Virtual Memory Usage',
'formatter' : 'format_bytes',
},
'memphy': {
'id':'lvememphy',
'description' : 'Physical Memory Usage',
'formatter' : 'format_bytes',
},
'nproc': {
'id':'lvenproc',
'description' : 'Number of Processes',
'formatter' : None,
},
'io': {
'id':'lveio',
'description' : 'I/O Usage',
'formatter' : 'format_bytes_per_second',
},
'iops': {
'id':'lveiops',
'description' : 'IOPS',
'formatter' : None,
},
'inodes': {
'id':'lveinodes',
'description' : 'Inodes',
'formatter' : None,
},
}
def is_normalize_user_cpu():
# default TRUE
CONFIG = '/etc/sysconfig/cloudlinux'
norm_cpu = get_param_from_file(CONFIG, 'normalized_user_cpu', '=')
if norm_cpu.upper() in ['N','NO','FALSE']:
return False
return True
def convert_cpu(kernel_cpu_limit, kernel_cpu_usage):
"""
Normilize cpu if needed
"""
if is_normalize_user_cpu():
return (100, int(float(kernel_cpu_usage) / kernel_cpu_limit * 100))
else:
return (int(float(kernel_cpu_limit) / 100), int(float(kernel_cpu_usage) / 100))
def convert_to_percent(limit, usage):
"""
Convert any limit/usage to percent
"""
percent = int((usage / limit) * 100)
return percent
def get_lve_limits_for_uid(uid, show_inode=False):
"""
Parse LVE_INFO and return line by ID
param:: uid - int
param:: show_inode - bool
return:: dict or None
"""
data = None
lines = get_file_lines(LVE_INFO)
if show_inode:
quota = get_quota_info(uid)
else:
quota = None
for line in lines:
line = line.strip()
line_parts = line.split(',')
if int(line_parts[ID_INDEX]) == uid:
data = {
'ep' : int(line_parts[EP_INDEX]),
'lep' : int(line_parts[LEP_INDEX]),
'cpu' : int(line_parts[CPU_INDEX]),
'lcpu' : int(line_parts[LCPU_INDEX]),
'mem' : int(line_parts[MEM_INDEX]) * MEMORY_PAGE_SIZE, #convert page to bytes
'lmem' : int(line_parts[LMEM_INDEX]) * MEMORY_PAGE_SIZE,
'memphy' : int(line_parts[PMEM_INDEX]) * MEMORY_PAGE_SIZE,
'lmemphy' : int(line_parts[LPMEM_INDEX]) * MEMORY_PAGE_SIZE,
'nproc' : int(line_parts[NPROC_INDEX]),
'lnproc' : int(line_parts[LNPROC_INDEX]),
'io' : int(line_parts[IO_INDEX]) * BYTES_IN_KILO,
'lio' : int(line_parts[LIO_INDEX]) * BYTES_IN_KILO,
'iops' : int(line_parts[IOPS_INDEX]),
'liops' : int(line_parts[LIOPS_INDEX]),
}
break
if int(line_parts[ID_INDEX]) == 0:
data_default = {
'ep' : int(line_parts[EP_INDEX]),
'lep' : int(line_parts[LEP_INDEX]),
'cpu' : int(line_parts[CPU_INDEX]),
'lcpu' : int(line_parts[LCPU_INDEX]),
'mem' : int(line_parts[MEM_INDEX]) * MEMORY_PAGE_SIZE, #convert page to bytes
'lmem' : int(line_parts[LMEM_INDEX]) * MEMORY_PAGE_SIZE,
'memphy' : int(line_parts[PMEM_INDEX]) * MEMORY_PAGE_SIZE,
'lmemphy' : int(line_parts[LPMEM_INDEX]) * MEMORY_PAGE_SIZE,
'nproc' : int(line_parts[NPROC_INDEX]),
'lnproc' : int(line_parts[LNPROC_INDEX]),
'io' : int(line_parts[IO_INDEX]) * BYTES_IN_KILO,
'lio' : int(line_parts[LIO_INDEX]) * BYTES_IN_KILO,
'iops' : int(line_parts[IOPS_INDEX]),
'liops' : int(line_parts[LIOPS_INDEX]),
}
# data can be None if all limits are default and no usage
# use default limits as lve limits
if data is None:
data = data_default
if quota is not None and show_inode:
data['inodes'] = int(quota[1])
data['linodes'] = int(quota[2])
return data
def get_quota_info(lve_id):
"""
Return qouta line by id
return list [id, usage, hard, soft] or None
"""
try:
(r, std_out) = exec_utility('/usr/bin/cl-quota', ['--user-id=%s' % lve_id, '--csv'])
except OSError:
return None
if r == 0:
try:
parts = std_out.split('\n', 1)
limits = parts[1].strip().split(',')
return limits
except IndexError:
return None
else:
return None
def build_stats_hash(limits_dict):
return_list = []
for limit, usage in LIMITS_LIST:
try:
if limits_dict[limit] == 0: #skip unlimited limit
continue
perl_hash = {
'id': template_dict[usage]['id'],
'description': template_dict[usage]['description'],
'maximum' : limits_dict[limit],
'usage' : limits_dict[usage]
}
if usage == 'cpu':
l, u = convert_cpu(limits_dict[limit], limits_dict[usage])
perl_hash['maximum'] = l
perl_hash['usage'] = u
if template_dict[usage]['formatter'] is not None:
perl_hash['formatter'] = template_dict[usage]['formatter']
if os.path.isfile(PERCENTS_STATS_MODE_FLAG):
# Convert to Percentage if appropriate flag exist and remove formatters
perl_hash['maximum'] = 100
perl_hash['usage'] = convert_to_percent(limits_dict[limit], limits_dict[usage])
perl_hash.pop('formatter', None)
return_list.append(perl_hash)
except KeyError: #skip missing limits
pass
return return_list
def get_config():
""" Return pair show_stats and show_inode based on cpanel.config"""
def parse_line(line):
return bool(int(line.split('=')[1].strip()))
ui_config = UIConfig().get_config()
lve_hideuserstat = ui_config.get('uiSettings', {}).get('hideLVEUserStat')
lve_showinodeusage = ui_config.get('inodeLimits', {}).get('showUserInodesUsage')
file_usage = False
CPANEL_CONFIG = '/var/cpanel/cpanel.config'
try:
cfg = get_file_lines(CPANEL_CONFIG)
for line in cfg:
if line.startswith('file_usage'):
file_usage = parse_line(line)
except IOError as e:
# LVEMAN-1412. Use default value if config file has wrong permissions
if e.errno != errno.EACCES:
raise
show_stats = not lve_hideuserstat
show_inode = not file_usage and lve_showinodeusage
return show_stats, show_inode
if __name__ == "__main__":
try:
lve_id = int(sys.argv[1])
show_stats, show_inode = get_config()
limits = None
if show_stats:
limits = get_lve_limits_for_uid(lve_id, show_inode)
if limits is not None:
print(json.dumps(build_stats_hash(limits)))
else:
print(json.dumps([]))
except IndexError:
print(json.dumps([]))