# Copyright (c) Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2018 All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os from distutils import version def myExec(str): handle = os.popen(str) return handle.read() class LiteSpeed: exist = False version = 'Unknown' suexec = False lve = False correctArch = False def __init__(self): self.exist = os.path.isfile('/usr/local/lsws') if os.path.isfile('/usr/local/lsws/bin/litespeed') and len(myExec('ps aux|grep litespeed').split('\n')) > 1: self.exist = True self.lve = '1' in myExec('grep enableLVE /usr/local/lsws/conf/httpd_config.xml') self.suexec = not ('0' in myExec('grep -i phpSuexec\> httpd_config.xml')) arch = myExec('file -L /usr/local/lsws/bin/litespeed') class ApacheInfo: exist = False version = 'Unknown' mpm = 'Unknown' hostinglimits = 'Unknown' fcgid = 'Unknown' cgi = 'Unknown' php_dso = 'Unknown' cgid = 'Unknown' suPHP = 'Unknown' fastcgi = 'Unknown' disable_suexec = 'Unknown' suexec = 'Unknown' moduleInfo = False modules = 'Unknown' def __init__(self, path): self.detect(path) def check_version(self): if version.LooseVersion(self.version) >= version.LooseVersion("2.2.0"): return True else: print_warning(3001, "Unable to determine list of loaded modules, apache version %s", self.apache.version) return False def isModule(self, name): return str(self.modules.find(" "+name+"_module") != -1) def parseModules(self): if self.moduleInfo: self.hostinglimits = self.isModule('hostinglimits') self.fcgid = self.isModule('fcgid') self.php_dso = self.isModule('php5') self.cgi = self.isModule('cgi') self.cgid = self.isModule('cgid') self.suPHP = self.isModule('suPHP') self.fastcgi = self.isModule('fastcgi') self.disable_suexec = self.isModule('disable_suexec') self.suexec = self.isModule('suexec') def detect(self, path): self.exist = os.path.isfile(path) if self.exist: tmp = myExec(path + " -V 2>&1") if tmp.find('Syntax error') >= 0: lsapi_conf = None for s in tmp.split(' '): if s.find('lsapi.conf') >= 0: lsapi_conf = s.replace(':', '') break if lsapi_conf is not None: myExec('mv ' + lsapi_conf + ' ' + lsapi_conf + '.SAVE') tmp = myExec(path + " -V 2>&1") if lsapi_conf is not None: myExec('mv ' + lsapi_conf + '.SAVE ' + lsapi_conf) lines = tmp.split('\n') for line in lines: if line.find('Server version:') != -1: self.version = line[line.find('/')+1:] if line.find('Server MPM:') != -1: self.mpm = line[line.rfind(' ')+1:] if version.LooseVersion(self.version) > version.LooseVersion('2.2'): self.moduleInfo = True self.modules = myExec(path + " -M 2>&1") self.parseModules() def str(self): if self.exist: str = "Apache verion: "+self.version+", mpm="+self.mpm+ \ ", hostinglimits="+self.hostinglimits+ \ ", cgi="+self.cgi+", cgid="+self.cgid+ \ ", fcgi="+self.fcgid+ ", fastcgi="+self.fastcgi+ \ ", php DSO="+self.php_dso+", suphp="+self.suPHP+ \ ", suexec="+self.suexec+", disable_suexec="+self.disable_suexec return str else: return None def print_error(code, error_str, error_list, solution): print("CODE: ", code) print(error_str % error_list) print("Solution: ", solution) def print_warning(code, error_str, error_list): print("WARNING: ", code) print(error_str % error_list) class Kernel: version = None isLVEKernel = False isVZKernel = False isLVEEnabled = False def __init__(self): self.kernelName = myExec('/bin/uname -r').rstrip('\n') self.isLVEKernel = self.kernelName.find('lve') if self.isLVEKernel != -1: self.version = self.kernelName[self.isLVEKernel+3:] self.isLVEEnabled = os.path.isfile('/proc/lve/list') else: self.isVZKernel = 'stab' in self.kernelName def check(self): if self.isLVEEnabled: if self.isLVEEnabled: if version.LooseVersion(self.version) > version.LooseVersion('0.8.28'): return True elif version.LooseVersion(self.version) > version.LooseVersion('0.8.0'): print_error(1001, "You are running bugy kernel LVE version %s", self.version, "Upgrade Kernel") elif version.LooseVersion(self.version) > version.LooseVersion('0.7.0'): print_error(1002, "You are running old kernel LVE version %s\n That version doesn't support multiple cores per LVE or memory limits", self.version, "Upgrade Kernel") else: print_error(1003, "You are running very old, bugy kernel, LVE version %s", self.version, "Upgrade Kernel") else: print_error(1004, "LVE is not enabled", (), "Check /etc/sysconfig/lve file, and make sure lve rpm is installed") elif self.isVZKernel: print_error(1101, "You are running VZ or OpenVZ", (), "CloudLinux is not compatible, see http://www.cloudlinux.com/vz-compat.php for more info") else: print_error(1201, "You are not running CloudLinux kernel. Your kernel is: %s", self.version, "Check /boot/grub/grub.conf") def str(self): result = "Kernel: " if self.isLVEEnabled: result += "OK (" + self.version + ")" elif self.isVZKernel: result += "VZ (" + self.kernelName + ")" else: result += "Unknown (" + self.kernelName + ")" return result class CP: name = "Unknown CP" version = "Unknown" kernel = None def __init__(self): self.apache = ApacheInfo('/usr/sbin/apachectl') self.apache_path = '/etc/httpd' self.kernel = Kernel() def str(self): return self.name + " " + self.version + " " + self.kernel.str() def __str__(self): return self.name def check(self): self.kernel.check() class CPanel(CP): def __init__(self): super(CPanel, self).__init__() self.name = "cPanel" self.version = myExec('/usr/local/cpanel/cpanel -V') self.apache = ApacheInfo('/usr/local/bin/apachectl') if os.path.exists('/etc/cpanel/ea4/is_ea4'): self.ea = 'EA4' self.apache_path = '/etc/apache2' else: self.ea = 'EA3' self.apache_path = '/usr/local/apache' def __str__(self): return self.ea class Plesk(CP): def __init__(self): super(Plesk, self).__init__() self.name = "Plesk" tmp = myExec('/bin/cat /usr/local/psa/version') self.version = tmp.split(' ')[0] self.apache = ApacheInfo('/usr/sbin/apachectl') class DirectAdmin(CP): def __init__(self): super(DirectAdmin, self).__init__() self.name = "DirectAdmin" tmp = myExec('/usr/local/directadmin/custombuild/build versions') tmp = tmp.split('\n') self.version = 'Unknown' self.apache = ApacheInfo('/usr/sbin/apachectl') for item in tmp: if item.find('Installed version of DirectAdmin:') != -1: self.version = item.split(':')[1].strip() break class HSphere(CP): def __init__(self): super(HSphere, self).__init__() self.name = "H-Sphere" tmp = myExec('/bin/cat /hsphere/local/home/cpanel/shiva/psoft_config/HS_VERSION') self.version = tmp.split('\n')[1].strip() self.apache = self.get_apache_type() def get_apache_type(self): if os.path.isfile('/hsphere/shared/scripts/scripts.cfg'): f = open('/hsphere/shared/scripts/scripts.cfg') lines = f.readlines() f.close() for item in lines: key = item.split('=')[0].strip() value = item.split('=')[1].strip() if key == 'apache_version': if value == '1': return ApacheInfo('/hsphere/shared/apache/bin/httpd') else: return ApacheInfo('/hsphere/shared/apache2/bin/apachectl') return ApacheInfo('') class iWorx(CP): def __init__(self): super(iWorx, self).__init__() self.name = "InterWorx" self.ini_file = '/usr/local/interworx/iworx.ini' self.version = self.find_version() self.apache = ApacheInfo('/usr/sbin/apachectl') def find_version(self): try: with open(self.ini_file, 'r') as ini_info: out = ini_info.read() return out.split('version')[4].replace('\n', '').replace('=', '').replace('"', '').split('[')[0] except Exception: return None class ISPMgr(CP): def __init__(self): super(ISPMgr, self).__init__() self.name = "ISPManager" self.version = "unk" self.apache = ApacheInfo('/usr/sbin/apachectl') class CustomPanel(CP): def __init__(self): super(CustomPanel, self).__init__() self.name = "CustomPanel" self.config_reader() self.root_dir = '/usr/share/lve/modlscapi/custom/' self.apache = None def config_reader(self): """Read all configurations related to Custom Panel from config.ini in the 'root_dir' folder. config.ini file must include GLOBAL section. """ import configparser config = configparser.ConfigParser() config.read(self.root_dir + 'config.ini') cp_config = config['GLOBAL'] self.check_config_ini(cp_config) self.version = cp_config.get('VERSION') self.apachectl= cp_config.get('APACHECTL_BIN_LOCATION') self.doc_url = cp_config.get('DOC_URL') self.executable= cp_config.get('EXECUTABLE_BIN') self.panel_name = cp_config.get('PANEL_NAME') if self.apachectl: self.apache = ApacheInfo(self.apachectl) def check_config_ini(self, cp_config): # If we add some directive to config.ini as a new feature or delete one of them, we have update this list too. # With this list we check if user supplied all required keys. required_keys = ['version', 'apachectl_bin_location', 'doc_url', 'executable_bin', 'panel_name'] missing_keys = [] for key in required_keys: if cp_config.get(key) is None: missing_keys.append(key) if missing_keys: print(f'Config file is missing required keys: {missing_keys}') exit(1) def get_cp(): if os.path.isfile('/usr/local/cpanel/cpanel'): cp = CPanel() elif os.path.isfile('/usr/local/psa/version'): cp = Plesk() elif os.path.isdir('/usr/local/directadmin') and os.path.isfile('/usr/local/directadmin/custombuild/build'): cp = DirectAdmin() elif os.path.isfile('/hsphere/local/home/cpanel/shiva/psoft_config/HS_VERSION'): cp = HSphere() elif os.path.isdir("/usr/local/ispmgr"): cp = ISPMgr() elif os.path.isfile('/usr/local/interworx/iworx.ini'): cp = iWorx() elif os.path.isfile('/usr/share/lve/modlscapi/custom/config.ini'): cp = CustomPanel() else: cp = CP() return cp