"""WOInfo Plugin for WordOps""" import configparser import os from cement.core.controller import CementBaseController, expose from wo.core.aptget import WOAptGet from wo.core.logging import Log from wo.core.variables import WOVar from wo.core.mysql import WOMysql def wo_info_hook(app): pass class WOInfoController(CementBaseController): class Meta: label = 'info' stacked_on = 'base' stacked_type = 'nested' description = ('Display configuration information related to ' 'OpenLiteSpeed, PHP and MySQL') arguments = [ (['--mysql'], dict(help='Get MySQL configuration information', action='store_true')), (['--php'], dict(help='Get PHP configuration information', action='store_true')), (['--nginx'], dict(help='Get OpenLiteSpeed configuration information', action='store_true')), ] usage = "wo info [options]" for php_version, php_number in WOVar.wo_php_versions.items(): arguments.append(([f'--{php_version}'], dict(help=f'Get PHP {php_number} configuration information', action='store_true'))) @expose(hide=True) def info_ols(self): """Display OpenLiteSpeed information""" version = os.popen("{0} -v 2>&1 | head -1" .format(WOVar.wo_ols_bin)).read().strip() httpd_conf = '{0}/httpd_config.conf'.format(WOVar.wo_ols_conf_dir) server_name = os.popen("hostname -f 2>/dev/null || hostname" ).read().strip() # Parse OLS httpd_config.conf for key settings max_connections = '' max_ssl_connections = '' keepalive_timeout = '' gzip_compress = '' brotli_compress = '' quic_enabled = '' if os.path.isfile(httpd_conf): with open(httpd_conf, 'r', encoding='utf-8') as f: for line in f: stripped = line.strip() parts = stripped.split(None, 1) if len(parts) == 2: key, val = parts if key == 'maxConnections': max_connections = val elif key == 'maxSSLConnections': max_ssl_connections = val elif key == 'keepAliveTimeout': keepalive_timeout = val elif key == 'enableGzipCompress': gzip_compress = 'On' if val == '1' else 'Off' elif key == 'enableBr': brotli_compress = 'On' if val == '1' else 'Off' elif key == 'enableQuic': quic_enabled = 'On' if val == '1' else 'Off' data = dict(version=version, server_name=server_name, max_connections=max_connections, max_ssl_connections=max_ssl_connections, keepalive_timeout=keepalive_timeout, gzip_compress=gzip_compress, brotli_compress=brotli_compress, quic_enabled=quic_enabled) self.app.render((data), 'info_ols.mustache') @expose(hide=True) def info_php(self): """Display PHP information""" pargs = self.app.pargs for parg_version, dot_ver in WOVar.wo_php_versions.items(): short_ver = dot_ver.replace('.', '') if WOAptGet.is_installed(self, 'lsphp{0}'.format(short_ver)): setattr(pargs, parg_version, True) else: Log.info(self, "PHP {0} is not installed".format(dot_ver)) for parg_version, dot_ver in WOVar.wo_php_versions.items(): if getattr(pargs, parg_version, False): short_ver = dot_ver.replace('.', '') self._info_lsphp(short_ver, dot_ver) @expose(hide=True) def _info_lsphp(self, short_ver, dot_ver): """Display LSPHP information for a given version""" php_bin = '/usr/local/lsws/lsphp{0}/bin/php'.format(short_ver) php_ini = ('/usr/local/lsws/lsphp{0}/etc/php/{1}' '/litespeed/php.ini'.format(short_ver, dot_ver)) version = os.popen("{0} -v 2>/dev/null | " "head -n1 | cut -d' ' -f2 |" " cut -d'+' -f1 | tr -d '\\n'" .format(php_bin)).read() config = configparser.ConfigParser() if os.path.isfile(php_ini): config.read(php_ini) else: Log.info(self, "LSPHP {0} php.ini not found at {1}" .format(dot_ver, php_ini)) return try: expose_php = config['PHP']['expose_php'] except KeyError: expose_php = 'N/A' try: memory_limit = config['PHP']['memory_limit'] except KeyError: memory_limit = 'N/A' try: post_max_size = config['PHP']['post_max_size'] except KeyError: post_max_size = 'N/A' try: upload_max_filesize = config['PHP']['upload_max_filesize'] except KeyError: upload_max_filesize = 'N/A' try: max_execution_time = config['PHP']['max_execution_time'] except KeyError: max_execution_time = 'N/A' data = dict(version=version, expose_php=expose_php, memory_limit=memory_limit, post_max_size=post_max_size, upload_max_filesize=upload_max_filesize, max_execution_time=max_execution_time, www_listen='LSAPI (managed by OLS)', www_ping_path='N/A', www_pm_status_path='N/A', www_pm='N/A', www_pm_max_requests='N/A', www_pm_max_children='N/A', www_pm_start_servers='N/A', www_pm_min_spare_servers='N/A', www_pm_max_spare_servers='N/A', www_request_terminate_timeout='N/A', www_xdebug_profiler_enable_trigger='N/A', debug_listen='N/A', debug_ping_path='N/A', debug_pm_status_path='N/A', debug_pm='N/A', debug_pm_max_requests='N/A', debug_pm_max_children='N/A', debug_pm_start_servers='N/A', debug_pm_min_spare_servers='N/A', debug_pm_max_spare_servers='N/A', debug_request_terminate_timeout='N/A', debug_xdebug_profiler_enable_trigger='N/A') self.app.render((data), 'info_php.mustache') @expose(hide=True) def info_mysql(self): """Display MySQL information""" if os.path.exists('/usr/bin/mariadb'): mariadb_exec = "/usr/bin/mariadb" else: mariadb_exec = "/usr/bin/mysql" version = os.popen(f"{mariadb_exec} -V |" "awk '{print($5)}' | " "cut -d ',' " "-f1 | tr -d '\n'").read() host = "localhost" port = os.popen(f"{mariadb_exec} -e \"show variables\" | " "/bin/grep ^port | awk " "'{print($2)}' | tr -d '\n'").read() wait_timeout = os.popen(f"{mariadb_exec} -e \"show variables\" | grep " "^wait_timeout | awk '{print($2)}' | " "tr -d '\n'").read() interactive_timeout = os.popen(f"{mariadb_exec} -e " "\"show variables\" | grep " "^interactive_timeout | awk " "'{print($2)}' | tr -d '\n'").read() max_used_connections = os.popen(f"{mariadb_exec} - e " "\"show global status\" | " "grep Max_used_connections | awk " "'{print($2)}' | tr -d '\n'").read() datadir = os.popen(f"{mariadb_exec} -e \"show variables\" | " "/bin/grep datadir | awk" " '{print($2)}' | tr -d '\n'").read() socket = os.popen(f"{mariadb_exec} -e \"show variables\" | " "/bin/grep \"^socket\" | " "awk '{print($2)}' | tr -d '\n'").read() data = dict(version=version, host=host, port=port, wait_timeout=wait_timeout, interactive_timeout=interactive_timeout, max_used_connections=max_used_connections, datadir=datadir, socket=socket) self.app.render((data), 'info_mysql.mustache') @expose(hide=True) def default(self): """default function for info""" pargs = self.app.pargs if (not pargs.nginx and not pargs.php and not pargs.mysql): pargs.nginx = True pargs.mysql = True pargs.php = True if pargs.nginx: if ((not WOAptGet.is_installed(self, 'openlitespeed')) and (not os.path.exists(WOVar.wo_ols_bin))): Log.info(self, "OpenLiteSpeed is not installed") else: self.info_ols() if pargs.php: self.info_php() if pargs.mysql: if WOMysql.mariadb_ping(self): self.info_mysql() else: Log.info(self, "MySQL is not installed") def load(app): # register the plugin class.. this only happens if the plugin is enabled app.handler.register(WOInfoController) # register a hook (function) to run after arguments are parsed. app.hook.register('post_argument_parsing', wo_info_hook)