Refactored

This commit is contained in:
jeroenops
2018-11-13 21:55:59 +01:00
commit b36df4384a
129 changed files with 14400 additions and 0 deletions

0
wo/cli/__init__.py Normal file
View File

11
wo/cli/bootstrap.py Normal file
View File

@@ -0,0 +1,11 @@
"""WordOps bootstrapping."""
# All built-in application controllers should be imported, and registered
# in this file in the same way as WOBaseController.
from cement.core import handler
from wo.cli.controllers.base import WOBaseController
def load(app):
handler.register(WOBaseController)

View File

View File

@@ -0,0 +1,25 @@
"""WordOps base controller."""
from cement.core.controller import CementBaseController, expose
from wo.core.variables import WOVariables
VERSION = WOVariables.wo_version
BANNER = """
WordOps v%s
Copyright (c) 2018 WordOps.
""" % VERSION
class WOBaseController(CementBaseController):
class Meta:
label = 'base'
description = ("WordOps is the commandline tool to manage your"
" websites based on WordPress and Nginx with easy to"
" use commands")
arguments = [
(['-v', '--version'], dict(action='version', version=BANNER)),
]
@expose(hide=True)
def default(self):
self.app.args.print_help()

0
wo/cli/ext/__init__.py Normal file
View File

View File

@@ -0,0 +1,20 @@
# Based on https://github.com/datafolklabs/cement/issues/295
# To avoid encoding releated error,we defined our custom output handler
# I hope we will remove this when we upgarde to Cement 2.6 (Not released yet)
import os
from cement.utils import fs
from cement.ext.ext_mustache import MustacheOutputHandler
class WOOutputHandler(MustacheOutputHandler):
class Meta:
label = 'wo_output_handler'
def _load_template_from_file(self, path):
for templ_dir in self.app._meta.template_dirs:
full_path = fs.abspath(os.path.join(templ_dir, path))
if os.path.exists(full_path):
self.app.log.debug('loading template file %s' % full_path)
return open(full_path, encoding='utf-8', mode='r').read()
else:
continue

135
wo/cli/main.py Normal file
View File

@@ -0,0 +1,135 @@
"""WordOps main application entry point."""
import sys
import os
# this has to happen after you import sys, but before you import anything
# from Cement "source: https://github.com/datafolklabs/cement/issues/290"
if '--debug' in sys.argv:
sys.argv.remove('--debug')
TOGGLE_DEBUG = True
else:
TOGGLE_DEBUG = False
from cement.core import foundation
from cement.utils.misc import init_defaults
from cement.core.exc import FrameworkError, CaughtSignal
from cement.ext.ext_argparse import ArgParseArgumentHandler
from wo.core import exc
from wo.cli.ext.wo_outputhandler import WOOutputHandler
# Application default. Should update config/wo.conf to reflect any
# changes, or additions here.
defaults = init_defaults('wo')
# All internal/external plugin configurations are loaded from here
defaults['wo']['plugin_config_dir'] = '/etc/wo/plugins.d'
# External plugins (generally, do not ship with application code)
defaults['wo']['plugin_dir'] = '/var/lib/wo/plugins'
# External templates (generally, do not ship with application code)
defaults['wo']['template_dir'] = '/var/lib/wo/templates'
class WOArgHandler(ArgParseArgumentHandler):
class Meta:
label = 'wo_args_handler'
def error(self, message):
super(WOArgHandler, self).error("unknown args")
class WOApp(foundation.CementApp):
class Meta:
label = 'wo'
config_defaults = defaults
# All built-in application bootstrapping (always run)
bootstrap = 'wo.cli.bootstrap'
# Optional plugin bootstrapping (only run if plugin is enabled)
plugin_bootstrap = 'wo.cli.plugins'
# Internal templates (ship with application code)
template_module = 'wo.cli.templates'
# Internal plugins (ship with application code)
plugin_bootstrap = 'wo.cli.plugins'
extensions = ['mustache']
# default output handler
output_handler = WOOutputHandler
arg_handler = WOArgHandler
debug = TOGGLE_DEBUG
class WOTestApp(WOApp):
"""A test app that is better suited for testing."""
class Meta:
argv = []
config_files = []
# Define the applicaiton object outside of main, as some libraries might wish
# to import it as a global (rather than passing it into another class/func)
app = WOApp()
def main():
try:
global sys
# Default our exit status to 0 (non-error)
code = 0
# if not root...kick out
if not os.geteuid() == 0:
print("\nNon-privileged users cant use WordOps. Switch to root or invoke sudo.\n")
app.close(1)
# Setup the application
app.setup()
# Dump all arguments into wo log
app.log.debug(sys.argv)
# Run the application
app.run()
except exc.WOError as e:
# Catch our application errors and exit 1 (error)
code = 1
print(e)
except FrameworkError as e:
# Catch framework errors and exit 1 (error)
code = 1
print(e)
except CaughtSignal as e:
# Default Cement signals are SIGINT and SIGTERM, exit 0 (non-error)
code = 0
print(e)
except Exception as e:
code = 1
print(e)
finally:
# Print an exception (if it occurred) and --debug was passed
if app.debug:
import sys
import traceback
exc_type, exc_value, exc_traceback = sys.exc_info()
if exc_traceback is not None:
traceback.print_exc()
# # Close the application
app.close(code)
def get_test_app(**kw):
app = WOApp(**kw)
return app
if __name__ == '__main__':
main()

View File

104
wo/cli/plugins/clean.py Normal file
View File

@@ -0,0 +1,104 @@
"""Clean Plugin for WordOps."""
from wo.core.shellexec import WOShellExec
from wo.core.aptget import WOAptGet
from wo.core.services import WOService
from wo.core.logging import Log
from cement.core.controller import CementBaseController, expose
from cement.core import handler, hook
import os
import urllib.request
def wo_clean_hook(app):
pass
class WOCleanController(CementBaseController):
class Meta:
label = 'clean'
stacked_on = 'base'
stacked_type = 'nested'
description = ('Clean NGINX FastCGI cache, Opcache, Memcache, Redis Cache')
arguments = [
(['--all'],
dict(help='Clean all cache', action='store_true')),
(['--fastcgi'],
dict(help='Clean FastCGI cache', action='store_true')),
(['--memcache'],
dict(help='Clean MemCache', action='store_true')),
(['--opcache'],
dict(help='Clean OpCache', action='store_true')),
(['--redis'],
dict(help='Clean Redis Cache', action='store_true')),
]
usage = "wo clean [options]"
@expose(hide=True)
def default(self):
if (not (self.app.pargs.all or self.app.pargs.fastcgi or
self.app.pargs.memcache or self.app.pargs.opcache or
self.app.pargs.redis)):
self.clean_fastcgi()
if self.app.pargs.all:
self.clean_memcache()
self.clean_fastcgi()
self.clean_opcache()
self.clean_redis()
if self.app.pargs.fastcgi:
self.clean_fastcgi()
if self.app.pargs.memcache:
self.clean_memcache()
if self.app.pargs.opcache:
self.clean_opcache()
if self.app.pargs.redis:
self.clean_redis()
@expose(hide=True)
def clean_redis(self):
"""This function clears Redis cache"""
if(WOAptGet.is_installed(self, "redis-server")):
Log.info(self, "Cleaning Redis cache")
WOShellExec.cmd_exec(self, "redis-cli flushall")
else:
Log.info(self, "Redis is not installed")
@expose(hide=True)
def clean_memcache(self):
try:
if(WOAptGet.is_installed(self, "memcached")):
WOService.restart_service(self, "memcached")
Log.info(self, "Cleaning MemCache")
else:
Log.info(self, "Memcache not installed")
except Exception as e:
Log.debug(self, "{0}".format(e))
Log.error(self, "Unable to restart Memcached", False)
@expose(hide=True)
def clean_fastcgi(self):
if(os.path.isdir("/var/run/nginx-cache")):
Log.info(self, "Cleaning NGINX FastCGI cache")
WOShellExec.cmd_exec(self, "rm -rf /var/run/nginx-cache/*")
else:
Log.error(self, "Unable to clean FastCGI cache", False)
@expose(hide=True)
def clean_opcache(self):
try:
Log.info(self, "Cleaning opcache")
wp = urllib.request.urlopen(" https://127.0.0.1:22222/cache"
"/opcache/opgui.php?page=reset").read()
except Exception as e:
Log.debug(self, "{0}".format(e))
Log.debug(self, "Unable hit url, "
" https://127.0.0.1:22222/cache/opcache/opgui.php?page=reset,"
" please check you have admin tools installed")
Log.debug(self, "please check you have admin tools installed,"
" or install them with `wo stack install --admin`")
Log.error(self, "Unable to clean opcache", False)
def load(app):
# register the plugin class.. this only happens if the plugin is enabled
handler.register(WOCleanController)
# register a hook (function) to run after arguments are parsed.
hook.register('post_argument_parsing', wo_clean_hook)

856
wo/cli/plugins/debug.py Normal file
View File

@@ -0,0 +1,856 @@
"""Debug Plugin for WordOps"""
from cement.core.controller import CementBaseController, expose
from cement.core import handler, hook
from wo.core.aptget import WOAptGet
from wo.core.shellexec import *
from wo.core.mysql import WOMysql
from wo.core.services import WOService
from wo.core.logging import Log
from wo.cli.plugins.site_functions import logwatch
from wo.core.variables import WOVariables
from wo.core.fileutils import WOFileUtils
from pynginxconfig import NginxConfig
import os
import configparser
import glob
import signal
import subprocess
def wo_debug_hook(app):
pass
class WODebugController(CementBaseController):
class Meta:
label = 'debug'
description = 'Used for server level debugging'
stacked_on = 'base'
stacked_type = 'nested'
arguments = [
(['--stop'],
dict(help='Stop debug', action='store_true')),
(['--start'],
dict(help='Start debug', action='store_true')),
(['--import-slow-log'],
dict(help='Import MySQL slow log to Anemometer database',
action='store_true')),
(['--nginx'],
dict(help='start/stop debugging nginx server '
'configuration for site',
action='store' or 'store_const',
choices=('on', 'off'), const='on', nargs='?')),
(['--php'],
dict(help='start/stop debugging server PHP configuration',
action='store' or 'store_const',
choices=('on', 'off'), const='on', nargs='?')),
(['--fpm'],
dict(help='start/stop debugging fastcgi configuration',
action='store' or 'store_const',
choices=('on', 'off'), const='on', nargs='?')),
(['--php7'],
dict(help='start/stop debugging server PHP 7 configuration',
action='store' or 'store_const',
choices=('on', 'off'), const='on', nargs='?')),
(['--fpm7'],
dict(help='start/stop debugging fastcgi 7.0 configuration',
action='store' or 'store_const',
choices=('on', 'off'), const='on', nargs='?')),
(['--mysql'],
dict(help='start/stop debugging MySQL server',
action='store' or 'store_const',
choices=('on', 'off'), const='on', nargs='?')),
(['--wp'],
dict(help='start/stop wordpress debugging for site',
action='store' or 'store_const', choices=('on', 'off'),
const='on', nargs='?')),
(['--rewrite'],
dict(help='start/stop debugging nginx rewrite rules for site',
action='store' or 'store_const', choices=('on', 'off'),
const='on', nargs='?')),
(['--all'],
dict(help='start/stop debugging all server parameters',
action='store' or 'store_const', choices=('on', 'off'),
const='on', nargs='?')),
(['-i', '--interactive'],
dict(help='Interactive debug', action='store_true')),
(['--import-slow-log-interval'],
dict(help='Import MySQL slow log to Anemometer',
action='store', dest='interval')),
(['site_name'],
dict(help='Website Name', nargs='?', default=None))
]
usage = "wo debug [<site_name>] [options] "
@expose(hide=True)
def debug_nginx(self):
"""Start/Stop Nginx debug"""
# start global debug
if (self.app.pargs.nginx == 'on' and not self.app.pargs.site_name):
try:
debug_address = (self.app.config.get('stack', 'ip-address')
.split())
except Exception as e:
debug_address = ['0.0.0.0/0']
# Check if IP address is 127.0.0.1 then enable debug globally
if debug_address == ['127.0.0.1'] or debug_address == []:
debug_address = ['0.0.0.0/0']
for ip_addr in debug_address:
if not ("debug_connection "+ip_addr in open('/etc/nginx/'
'nginx.conf', encoding='utf-8').read()):
Log.info(self, "Setting up Nginx debug connection"
" for "+ip_addr)
WOShellExec.cmd_exec(self, "sed -i \"/events {{/a\\ \\ \\ "
"\\ $(echo debug_connection "
"{ip}\;)\" /etc/nginx/"
"nginx.conf".format(ip=ip_addr))
self.trigger_nginx = True
if not self.trigger_nginx:
Log.info(self, "Nginx debug connection already enabled")
self.msg = self.msg + ["/var/log/nginx/*.error.log"]
# stop global debug
elif (self.app.pargs.nginx == 'off' and not self.app.pargs.site_name):
if "debug_connection " in open('/etc/nginx/nginx.conf',
encoding='utf-8').read():
Log.info(self, "Disabling Nginx debug connections")
WOShellExec.cmd_exec(self, "sed -i \"/debug_connection.*/d\""
" /etc/nginx/nginx.conf")
self.trigger_nginx = True
else:
Log.info(self, "Nginx debug connection already disabled")
# start site specific debug
elif (self.app.pargs.nginx == 'on' and self.app.pargs.site_name):
config_path = ("/etc/nginx/sites-available/{0}"
.format(self.app.pargs.site_name))
if os.path.isfile(config_path):
if not WOShellExec.cmd_exec(self, "grep \"error.log debug\" "
"{0}".format(config_path)):
Log.info(self, "Starting NGINX debug connection for "
"{0}".format(self.app.pargs.site_name))
WOShellExec.cmd_exec(self, "sed -i \"s/error.log;/"
"error.log "
"debug;/\" {0}".format(config_path))
self.trigger_nginx = True
else:
Log.info(self, "Nginx debug for site already enabled")
self.msg = self.msg + ['{0}{1}/logs/error.log'
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
else:
Log.info(self, "{0} domain not valid"
.format(self.app.pargs.site_name))
# stop site specific debug
elif (self.app.pargs.nginx == 'off' and self.app.pargs.site_name):
config_path = ("/etc/nginx/sites-available/{0}"
.format(self.app.pargs.site_name))
if os.path.isfile(config_path):
if WOShellExec.cmd_exec(self, "grep \"error.log debug\" {0}"
.format(config_path)):
Log.info(self, "Stoping NGINX debug connection for {0}"
.format(self.app.pargs.site_name))
WOShellExec.cmd_exec(self, "sed -i \"s/error.log debug;/"
"error.log;/\" {0}"
.format(config_path))
self.trigger_nginx = True
else:
Log.info(self, "Nginx debug for site already disabled")
else:
Log.info(self, "{0} domain not valid"
.format(self.app.pargs.site_name))
@expose(hide=True)
def debug_php(self):
"""Start/Stop PHP debug"""
# PHP global debug start
if (self.app.pargs.php == 'on' and not self.app.pargs.site_name):
if not (WOShellExec.cmd_exec(self, "sed -n \"/upstream php"
"{/,/}/p \" /etc/nginx/"
"conf.d/upstream.conf "
"| grep 9001")):
Log.info(self, "Enabling PHP debug")
# Change upstream.conf
nc = NginxConfig()
nc.loadf('/etc/nginx/conf.d/upstream.conf')
nc.set([('upstream','php',), 'server'], '127.0.0.1:9001')
if os.path.isfile("/etc/nginx/common/wpfc-hhvm.conf"):
nc.set([('upstream','hhvm',), 'server'], '127.0.0.1:9001')
nc.savef('/etc/nginx/conf.d/upstream.conf')
# Enable xdebug
WOFileUtils.searchreplace(self, "/etc/{0}/mods-available/".format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5") +
"xdebug.ini",
";zend_extension",
"zend_extension")
# Fix slow log is not enabled default in PHP5.6
config = configparser.ConfigParser()
config.read('/etc/{0}/fpm/pool.d/debug.conf'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5"))
config['debug']['slowlog'] = '/var/log/{0}/slow.log'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5")
config['debug']['request_slowlog_timeout'] = '10s'
with open('/etc/{0}/fpm/pool.d/debug.conf'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5"),
encoding='utf-8', mode='w') as confifile:
Log.debug(self, "Writting debug.conf configuration into "
"/etc/{0}/fpm/pool.d/debug.conf".format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5"))
config.write(confifile)
self.trigger_php = True
self.trigger_nginx = True
else:
Log.info(self, "PHP debug is already enabled")
self.msg = self.msg + ['/var/log/{0}/slow.log'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5")]
# PHP global debug stop
elif (self.app.pargs.php == 'off' and not self.app.pargs.site_name):
if WOShellExec.cmd_exec(self, " sed -n \"/upstream php {/,/}/p\" "
"/etc/nginx/conf.d/upstream.conf "
"| grep 9001"):
Log.info(self, "Disabling PHP debug")
# Change upstream.conf
nc = NginxConfig()
nc.loadf('/etc/nginx/conf.d/upstream.conf')
nc.set([('upstream','php',), 'server'], '127.0.0.1:9000')
if os.path.isfile("/etc/nginx/common/wpfc-hhvm.conf"):
nc.set([('upstream','hhvm',), 'server'], '127.0.0.1:8000')
nc.savef('/etc/nginx/conf.d/upstream.conf')
# Disable xdebug
WOFileUtils.searchreplace(self, "/etc/{0}/mods-available/".format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5") +
"xdebug.ini",
"zend_extension",
";zend_extension")
self.trigger_php = True
self.trigger_nginx = True
else:
Log.info(self, "PHP debug is already disabled")
@expose(hide=True)
def debug_fpm(self):
"""Start/Stop PHP5-FPM debug"""
# PHP5-FPM start global debug
if (self.app.pargs.fpm == 'on' and not self.app.pargs.site_name):
if not WOShellExec.cmd_exec(self, "grep \"log_level = debug\" "
"/etc/{0}/fpm/php-fpm.conf".format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5")):
Log.info(self, "Setting up PHP5-FPM log_level = debug")
config = configparser.ConfigParser()
config.read('/etc/{0}/fpm/php-fpm.conf'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5"))
config.remove_option('global', 'include')
config['global']['log_level'] = 'debug'
config['global']['include'] = '/etc/{0}/fpm/pool.d/*.conf'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5")
with open('/etc/{0}/fpm/php-fpm.conf'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5"),
encoding='utf-8', mode='w') as configfile:
Log.debug(self, "Writting php5-FPM configuration into "
"/etc/{0}/fpm/php-fpm.conf".format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5"))
config.write(configfile)
self.trigger_php = True
else:
Log.info(self, "PHP5-FPM log_level = debug already setup")
self.msg = self.msg + ['/var/log/{0}/fpm.log'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5")]
# PHP5-FPM stop global debug
elif (self.app.pargs.fpm == 'off' and not self.app.pargs.site_name):
if WOShellExec.cmd_exec(self, "grep \"log_level = debug\" "
"/etc/{0}/fpm/php-fpm.conf".format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5")):
Log.info(self, "Disabling PHP5-FPM log_level = debug")
config = configparser.ConfigParser()
config.read('/etc/{0}/fpm/php-fpm.conf'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5"))
config.remove_option('global', 'include')
config['global']['log_level'] = 'notice'
config['global']['include'] = '/etc/{0}/fpm/pool.d/*.conf'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5")
with open('/etc/{0}/fpm/php-fpm.conf'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5"),
encoding='utf-8', mode='w') as configfile:
Log.debug(self, "writting php5 configuration into "
"/etc/{0}/fpm/php-fpm.conf".format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5"))
config.write(configfile)
self.trigger_php = True
else:
Log.info(self, "PHP5-FPM log_level = debug already disabled")
@expose(hide=True)
def debug_php7(self):
"""Start/Stop PHP debug"""
# PHP global debug start
if (self.app.pargs.php7 == 'on' and not self.app.pargs.site_name):
if (WOVariables.wo_platform_codename == 'wheezy' or WOVariables.wo_platform_codename == 'precise'):
Log.error(self,"PHP 7.0 not supported.")
if not (WOShellExec.cmd_exec(self, "sed -n \"/upstream php7"
"{/,/}/p \" /etc/nginx/"
"conf.d/upstream.conf "
"| grep 9170")):
Log.info(self, "Enabling PHP 7.0 debug")
# Change upstream.conf
nc = NginxConfig()
nc.loadf('/etc/nginx/conf.d/upstream.conf')
nc.set([('upstream','php7',), 'server'], '127.0.0.1:9170')
if os.path.isfile("/etc/nginx/common/wpfc-hhvm.conf"):
nc.set([('upstream','hhvm',), 'server'], '127.0.0.1:9170')
nc.savef('/etc/nginx/conf.d/upstream.conf')
# Enable xdebug
WOFileUtils.searchreplace(self, "/etc/php/7.0/mods-available/"
"xdebug.ini",
";zend_extension",
"zend_extension")
# Fix slow log is not enabled default in PHP5.6
config = configparser.ConfigParser()
config.read('/etc/php/7.0/fpm/pool.d/debug.conf')
config['debug']['slowlog'] = '/var/log/php/7.0/slow.log'
config['debug']['request_slowlog_timeout'] = '10s'
with open('/etc/php/7.0/fpm/pool.d/debug.conf',
encoding='utf-8', mode='w') as confifile:
Log.debug(self, "Writting debug.conf configuration into "
"/etc/php/7.0/fpm/pool.d/debug.conf")
config.write(confifile)
self.trigger_php = True
self.trigger_nginx = True
else:
Log.info(self, "PHP debug is already enabled")
self.msg = self.msg + ['/var/log/php/7.0/slow.log']
# PHP global debug stop
elif (self.app.pargs.php7 == 'off' and not self.app.pargs.site_name):
if WOShellExec.cmd_exec(self, " sed -n \"/upstream php7 {/,/}/p\" "
"/etc/nginx/conf.d/upstream.conf "
"| grep 9170"):
Log.info(self, "Disabling PHP 7.0 debug")
# Change upstream.conf
nc = NginxConfig()
nc.loadf('/etc/nginx/conf.d/upstream.conf')
nc.set([('upstream','php7',), 'server'], '127.0.0.1:9070')
if os.path.isfile("/etc/nginx/common/wpfc-hhvm.conf"):
nc.set([('upstream','hhvm',), 'server'], '127.0.0.1:8000')
nc.savef('/etc/nginx/conf.d/upstream.conf')
# Disable xdebug
WOFileUtils.searchreplace(self, "/etc/php/7.0/mods-available/"
"xdebug.ini",
"zend_extension",
";zend_extension")
self.trigger_php = True
self.trigger_nginx = True
else:
Log.info(self, "PHP 7.0 debug is already disabled")
@expose(hide=True)
def debug_fpm7(self):
"""Start/Stop PHP5-FPM debug"""
# PHP5-FPM start global debug
if (self.app.pargs.fpm7 == 'on' and not self.app.pargs.site_name):
if not WOShellExec.cmd_exec(self, "grep \"log_level = debug\" "
"/etc/php/7.0/fpm/php-fpm.conf"):
Log.info(self, "Setting up PHP7.0-FPM log_level = debug")
config = configparser.ConfigParser()
config.read('/etc/php/7.0/fpm/php-fpm.conf')
config.remove_option('global', 'include')
config['global']['log_level'] = 'debug'
config['global']['include'] = '/etc/php/7.0/fpm/pool.d/*.conf'
with open('/etc/php/7.0/fpm/php-fpm.conf',
encoding='utf-8', mode='w') as configfile:
Log.debug(self, "Writting php7.0-FPM configuration into "
"/etc/php/7.0/fpm/php-fpm.conf")
config.write(configfile)
self.trigger_php = True
else:
Log.info(self, "PHP7.0-FPM log_level = debug already setup")
self.msg = self.msg + ['/var/log/php/7.0/fpm.log']
# PHP5-FPM stop global debug
elif (self.app.pargs.fpm7 == 'off' and not self.app.pargs.site_name):
if WOShellExec.cmd_exec(self, "grep \"log_level = debug\" "
"/etc/php/7.0/fpm/php-fpm.conf"):
Log.info(self, "Disabling PHP7.0-FPM log_level = debug")
config = configparser.ConfigParser()
config.read('/etc/php/7.0/fpm/php-fpm.conf')
config.remove_option('global', 'include')
config['global']['log_level'] = 'notice'
config['global']['include'] = '/etc/php/7.0/fpm/pool.d/*.conf'
with open('/etc/php/7.0/fpm/php-fpm.conf',
encoding='utf-8', mode='w') as configfile:
Log.debug(self, "writting php7.0 configuration into "
"/etc/php/7.0/fpm/php-fpm.conf")
config.write(configfile)
self.trigger_php = True
else:
Log.info(self, "PHP7.0-FPM log_level = debug already disabled")
@expose(hide=True)
def debug_mysql(self):
"""Start/Stop MySQL debug"""
# MySQL start global debug
if (self.app.pargs.mysql == 'on' and not self.app.pargs.site_name):
if not WOShellExec.cmd_exec(self, "mysql -e \"show variables like"
" \'slow_query_log\';\" | "
"grep ON"):
Log.info(self, "Setting up MySQL slow log")
WOMysql.execute(self, "set global slow_query_log = "
"\'ON\';")
WOMysql.execute(self, "set global slow_query_log_file = "
"\'/var/log/mysql/mysql-slow.log\';")
WOMysql.execute(self, "set global long_query_time = 2;")
WOMysql.execute(self, "set global log_queries_not_using"
"_indexes = \'ON\';")
else:
Log.info(self, "MySQL slow log is already enabled")
self.msg = self.msg + ['/var/log/mysql/mysql-slow.log']
# MySQL stop global debug
elif (self.app.pargs.mysql == 'off' and not self.app.pargs.site_name):
if WOShellExec.cmd_exec(self, "mysql -e \"show variables like \'"
"slow_query_log\';\" | grep ON"):
Log.info(self, "Disabling MySQL slow log")
WOMysql.execute(self, "set global slow_query_log = \'OFF\';")
WOMysql.execute(self, "set global slow_query_log_file = \'"
"/var/log/mysql/mysql-slow.log\';")
WOMysql.execute(self, "set global long_query_time = 10;")
WOMysql.execute(self, "set global log_queries_not_using_index"
"es = \'OFF\';")
WOShellExec.cmd_exec(self, "crontab -l | sed \'/#WordOps "
"start/,/#WordOps end/d\' | crontab -")
else:
Log.info(self, "MySQL slow log already disabled")
@expose(hide=True)
def debug_wp(self):
"""Start/Stop WordPress debug"""
if (self.app.pargs.wp == 'on' and self.app.pargs.site_name):
wp_config = ("{0}/{1}/wp-config.php"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name))
webroot = "{0}{1}".format(WOVariables.wo_webroot,
self.app.pargs.site_name)
# Check wp-config.php file into htdocs folder
if not os.path.isfile(wp_config):
wp_config = ("{0}/{1}/htdocs/wp-config.php"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name))
if os.path.isfile(wp_config):
if not WOShellExec.cmd_exec(self, "grep \"\'WP_DEBUG\'\" {0} |"
" grep true".format(wp_config)):
Log.info(self, "Starting WordPress debug")
open("{0}/htdocs/wp-content/debug.log".format(webroot),
encoding='utf-8', mode='a').close()
WOShellExec.cmd_exec(self, "chown {1}: {0}/htdocs/wp-"
"content/debug.log"
"".format(webroot,
WOVariables.wo_php_user))
WOShellExec.cmd_exec(self, "sed -i \"s/define(\'WP_DEBUG\'"
".*/define(\'WP_DEBUG\', true);\\n"
"define(\'WP_DEBUG_DISPLAY\', false);"
"\\ndefine(\'WP_DEBUG_LOG\', true);"
"\\ndefine(\'SAVEQUERIES\', true);/\""
" {0}".format(wp_config))
WOShellExec.cmd_exec(self, "cd {0}/htdocs/ && wp"
" plugin --allow-root install "
"developer query-monitor"
.format(webroot))
WOShellExec.cmd_exec(self, "chown -R {1}: {0}/htdocs/"
"wp-content/plugins"
.format(webroot,
WOVariables.wo_php_user))
self.msg = self.msg + ['{0}{1}/htdocs/wp-content'
'/debug.log'
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
else:
Log.info(self, "Unable to find wp-config.php for site: {0}"
.format(self.app.pargs.site_name))
elif (self.app.pargs.wp == 'off' and self.app.pargs.site_name):
wp_config = ("{0}{1}/wp-config.php"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name))
webroot = "{0}{1}".format(WOVariables.wo_webroot,
self.app.pargs.site_name)
# Check wp-config.php file into htdocs folder
if not os.path.isfile(wp_config):
wp_config = ("{0}/{1}/htdocs/wp-config.php"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name))
if os.path.isfile(wp_config):
if WOShellExec.cmd_exec(self, "grep \"\'WP_DEBUG\'\" {0} | "
"grep true".format(wp_config)):
Log.info(self, "Disabling WordPress debug")
WOShellExec.cmd_exec(self, "sed -i \"s/define(\'WP_DEBUG\'"
", true);/define(\'WP_DEBUG\', "
"false);/\" {0}".format(wp_config))
WOShellExec.cmd_exec(self, "sed -i \"/define(\'"
"WP_DEBUG_DISPLAY\', false);/d\" {0}"
.format(wp_config))
WOShellExec.cmd_exec(self, "sed -i \"/define(\'"
"WP_DEBUG_LOG\', true);/d\" {0}"
.format(wp_config))
WOShellExec.cmd_exec(self, "sed -i \"/define(\'"
"SAVEQUERIES\', "
"true);/d\" {0}".format(wp_config))
else:
Log.info(self, "WordPress debug all already disabled")
else:
Log.error(self, "Missing argument site name")
@expose(hide=True)
def debug_rewrite(self):
"""Start/Stop Nginx rewrite rules debug"""
# Start Nginx rewrite debug globally
if (self.app.pargs.rewrite == 'on' and not self.app.pargs.site_name):
if not WOShellExec.cmd_exec(self, "grep \"rewrite_log on;\" "
"/etc/nginx/nginx.conf"):
Log.info(self, "Setting up Nginx rewrite logs")
WOShellExec.cmd_exec(self, "sed -i \'/http {/a \\\\t"
"rewrite_log on;\' /etc/nginx/nginx.conf")
self.trigger_nginx = True
else:
Log.info(self, "Nginx rewrite logs already enabled")
if '/var/log/nginx/*.error.log' not in self.msg:
self.msg = self.msg + ['/var/log/nginx/*.error.log']
# Stop Nginx rewrite debug globally
elif (self.app.pargs.rewrite == 'off'
and not self.app.pargs.site_name):
if WOShellExec.cmd_exec(self, "grep \"rewrite_log on;\" "
"/etc/nginx/nginx.conf"):
Log.info(self, "Disabling Nginx rewrite logs")
WOShellExec.cmd_exec(self, "sed -i \"/rewrite_log.*/d\""
" /etc/nginx/nginx.conf")
self.trigger_nginx = True
else:
Log.info(self, "Nginx rewrite logs already disabled")
# Start Nginx rewrite for site
elif (self.app.pargs.rewrite == 'on' and self.app.pargs.site_name):
config_path = ("/etc/nginx/sites-available/{0}"
.format(self.app.pargs.site_name))
if not WOShellExec.cmd_exec(self, "grep \"rewrite_log on;\" {0}"
.format(config_path)):
Log.info(self, "Setting up Nginx rewrite logs for {0}"
.format(self.app.pargs.site_name))
WOShellExec.cmd_exec(self, "sed -i \"/access_log/i \\\\\\t"
"rewrite_log on;\" {0}"
.format(config_path))
self.trigger_nginx = True
else:
Log.info(self, "Nginx rewrite logs for {0} already setup"
.format(self.app.pargs.site_name))
if ('{0}{1}/logs/error.log'.format(WOVariables.wo_webroot,
self.app.pargs.site_name)
not in self.msg):
self.msg = self.msg + ['{0}{1}/logs/error.log'
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
# Stop Nginx rewrite for site
elif (self.app.pargs.rewrite == 'off' and self.app.pargs.site_name):
config_path = ("/etc/nginx/sites-available/{0}"
.format(self.app.pargs.site_name))
if WOShellExec.cmd_exec(self, "grep \"rewrite_log on;\" {0}"
.format(config_path)):
Log.info(self, "Disabling Nginx rewrite logs for {0}"
.format(self.app.pargs.site_name))
WOShellExec.cmd_exec(self, "sed -i \"/rewrite_log.*/d\" {0}"
.format(config_path))
self.trigger_nginx = True
else:
Log.info(self, "Nginx rewrite logs for {0} already "
" disabled".format(self.app.pargs.site_name))
@expose(hide=True)
def signal_handler(self, signal, frame):
"""Handle Ctrl+c hevent for -i option of debug"""
self.start = False
if self.app.pargs.nginx:
self.app.pargs.nginx = 'off'
self.debug_nginx()
if self.app.pargs.php:
self.app.pargs.php = 'off'
self.debug_php()
if self.app.pargs.php7:
self.app.pargs.php7 = 'off'
self.debug_php7()
if self.app.pargs.fpm:
self.app.pargs.fpm = 'off'
self.debug_fpm()
if self.app.pargs.fpm7:
self.app.pargs.fpm7 = 'off'
self.debug_fpm7()
if self.app.pargs.mysql:
# MySQL debug will not work for remote MySQL
if WOVariables.wo_mysql_host is "localhost":
self.app.pargs.mysql = 'off'
self.debug_mysql()
else:
Log.warn(self, "Remote MySQL found, WordOps does not support "
"debugging remote servers")
if self.app.pargs.wp:
self.app.pargs.wp = 'off'
self.debug_wp()
if self.app.pargs.rewrite:
self.app.pargs.rewrite = 'off'
self.debug_rewrite()
# Reload Nginx
if self.trigger_nginx:
WOService.reload_service(self, 'nginx')
# Reload PHP
if self.trigger_php:
if WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic':
if WOAptGet.is_installed(self,'php5.6-fpm'):
WOService.reload_service(self, 'php5.6-fpm')
if WOAptGet.is_installed(self,'php7.0-fpm'):
WOService.reload_service(self, 'php7.0-fpm')
else:
WOService.reload_service(self, 'php5-fpm')
self.app.close(0)
@expose(hide=True)
def default(self):
"""Default function of debug"""
# self.start = True
self.interactive = False
self.msg = []
self.trigger_nginx = False
self.trigger_php = False
if ((not self.app.pargs.nginx) and (not self.app.pargs.php) and (not self.app.pargs.php7)
and (not self.app.pargs.fpm) and (not self.app.pargs.fpm7) and (not self.app.pargs.mysql)
and (not self.app.pargs.wp) and (not self.app.pargs.rewrite)
and (not self.app.pargs.all)
and (not self.app.pargs.site_name)
and (not self.app.pargs.import_slow_log)
and (not self.app.pargs.interval)):
if self.app.pargs.stop or self.app.pargs.start:
print("--start/stop option is deprecated since ee v3.0.5")
self.app.args.print_help()
else:
self.app.args.print_help()
if self.app.pargs.import_slow_log:
self.import_slow_log()
if self.app.pargs.interval:
try:
cron_time = int(self.app.pargs.interval)
except Exception as e:
cron_time = 5
try:
if not WOShellExec.cmd_exec(self, "crontab -l | grep "
"'wo debug --import-slow-log'"):
if not cron_time == 0:
Log.info(self, "setting up crontab entry,"
" please wait...")
WOShellExec.cmd_exec(self, "/bin/bash -c \"crontab -l "
"2> /dev/null | {{ cat; echo -e"
" \\\"#WordOps start MySQL "
"slow log \\n*/{0} * * * * "
"/usr/local/bin/wo debug"
" --import-slow-log\\n"
"#WordOps end MySQL slow log"
"\\\"; }} | crontab -\""
.format(cron_time))
else:
if not cron_time == 0:
Log.info(self, "updating crontab entry,"
" please wait...")
if not WOShellExec.cmd_exec(self, "/bin/bash -c "
"\"crontab "
"-l | sed '/WordOps "
"start MySQL slow "
"log/!b;n;c\*\/{0} "
"\* \* \* "
"\* \/usr"
"\/local\/bin\/wo debug "
"--import\-slow\-log' "
"| crontab -\""
.format(cron_time)):
Log.error(self, "failed to update crontab entry")
else:
Log.info(self, "removing crontab entry,"
" please wait...")
if not WOShellExec.cmd_exec(self, "/bin/bash -c "
"\"crontab "
"-l | sed '/WordOps "
"start MySQL slow "
"log/,+2d'"
"| crontab -\""
.format(cron_time)):
Log.error(self, "failed to remove crontab entry")
except CommandExecutionError as e:
Log.debug(self, str(e))
if self.app.pargs.all == 'on':
if self.app.pargs.site_name:
self.app.pargs.wp = 'on'
self.app.pargs.nginx = 'on'
self.app.pargs.php = 'on'
self.app.pargs.fpm = 'on'
if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') and WOAptGet.is_installed(self,'php7.0-fpm'):
self.app.pargs.php7 = 'on'
self.app.pargs.fpm7 = 'on'
self.app.pargs.mysql = 'on'
self.app.pargs.rewrite = 'on'
if self.app.pargs.all == 'off':
if self.app.pargs.site_name:
self.app.pargs.wp = 'off'
self.app.pargs.nginx = 'off'
self.app.pargs.php = 'off'
self.app.pargs.fpm = 'off'
if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') and WOAptGet.is_installed(self,'php7.0-fpm'):
self.app.pargs.php7 = 'off'
self.app.pargs.fpm7 = 'off'
self.app.pargs.mysql = 'off'
self.app.pargs.rewrite = 'off'
if ((not self.app.pargs.nginx) and (not self.app.pargs.php) and (not self.app.pargs.php7)
and (not self.app.pargs.fpm) and (not self.app.pargs.fpm7) and (not self.app.pargs.mysql)
and (not self.app.pargs.wp) and (not self.app.pargs.rewrite)
and self.app.pargs.site_name):
self.app.args.print_help()
# self.app.pargs.nginx = 'on'
# self.app.pargs.wp = 'on'
# self.app.pargs.rewrite = 'on'
if self.app.pargs.nginx:
self.debug_nginx()
if self.app.pargs.php:
self.debug_php()
if self.app.pargs.fpm:
self.debug_fpm()
if self.app.pargs.php7:
self.debug_php7()
if self.app.pargs.fpm7:
self.debug_fpm7()
if self.app.pargs.mysql:
# MySQL debug will not work for remote MySQL
if WOVariables.wo_mysql_host is "localhost":
self.debug_mysql()
else:
Log.warn(self, "Remote MySQL found, WordOps does not support "
"debugging remote servers")
if self.app.pargs.wp:
self.debug_wp()
if self.app.pargs.rewrite:
self.debug_rewrite()
if self.app.pargs.interactive:
self.interactive = True
# Reload Nginx
if self.trigger_nginx:
WOService.reload_service(self, 'nginx')
# Reload PHP
if self.trigger_php:
if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic'):
if WOAptGet.is_installed(self,'php5.6-fpm'):
WOService.restart_service(self, 'php5.6-fpm')
if WOAptGet.is_installed(self,'php7.0-fpm'):
WOService.restart_service(self, 'php7.0-fpm')
else:
WOService.restart_service(self, 'php5-fpm')
if WOVariables.wo_platform_codename == 'jessie':
WOService.restart_service(self, 'php7.0-fpm')
if len(self.msg) > 0:
if not self.app.pargs.interactive:
disp_msg = ' '.join(self.msg)
Log.info(self, "Use following command to check debug logs:\n"
+ Log.ENDC + "tail -f {0}".format(disp_msg))
else:
signal.signal(signal.SIGINT, self.signal_handler)
watch_list = []
for w_list in self.msg:
watch_list = watch_list + glob.glob(w_list)
logwatch(self, watch_list)
@expose(hide=True)
def import_slow_log(self):
"""Default function for import slow log"""
if os.path.isdir("{0}22222/htdocs/db/anemometer"
.format(WOVariables.wo_webroot)):
if os.path.isfile("/var/log/mysql/mysql-slow.log"):
# Get Anemometer user name and password
Log.info(self, "Importing MySQL slow log to Anemometer")
host = os.popen("grep -e \"\'host\'\" {0}22222/htdocs/"
.format(WOVariables.wo_webroot)
+ "db/anemometer/conf/config.inc.php "
"| head -1 | cut -d\\\' -f4 | "
"tr -d '\n'").read()
user = os.popen("grep -e \"\'user\'\" {0}22222/htdocs/"
.format(WOVariables.wo_webroot)
+ "db/anemometer/conf/config.inc.php "
"| head -1 | cut -d\\\' -f4 | "
"tr -d '\n'").read()
password = os.popen("grep -e \"\'password\'\" {0}22222/"
.format(WOVariables.wo_webroot)
+ "htdocs/db/anemometer/conf"
"/config.inc.php "
"| head -1 | cut -d\\\' -f4 | "
"tr -d '\n'").read()
# Import slow log Anemometer using pt-query-digest
try:
WOShellExec.cmd_exec(self, "pt-query-digest --user={0} "
"--password={1} "
"--review D=slow_query_log,"
"t=global_query_review "
"--history D=slow_query_log,t="
"global_query_review_history "
"--no-report --limit=0% "
"--filter=\" \\$event->{{Bytes}} = "
"length(\\$event->{{arg}}) "
"and \\$event->{{hostname}}=\\\""
"{2}\\\"\" "
"/var/log/mysql/mysql-slow.log"
.format(user, password, host))
except CommandExecutionError as e:
Log.debug(self, str(e))
Log.error(self, "MySQL slow log import failed.")
else:
Log.error(self, "MySQL slow log file not found,"
" so not imported slow logs")
else:
Log.error(self, "Anemometer is not installed." +
Log.ENDC + "\n Install Anemometer with:"
+ Log.BOLD + "\n `wo stack install --utils`"
+ Log.ENDC)
def load(app):
# register the plugin class.. this only happens if the plugin is enabled
handler.register(WODebugController)
# register a hook (function) to run after arguments are parsed.
hook.register('post_argument_parsing', wo_debug_hook)

View File

@@ -0,0 +1,34 @@
from cement.core.controller import CementBaseController, expose
from cement.core import handler, hook
from wo.core.shellexec import WOShellExec
from wo.core.logging import Log
from wo.core.variables import WOVariables
import os
def wo_import_slow_log_hook(app):
pass
class WOImportslowlogController(CementBaseController):
class Meta:
label = 'import_slow_log'
stacked_on = 'base'
stacked_type = 'nested'
description = 'Import MySQL slow log to Anemometer database'
usage = "wo import-slow-log"
@expose(hide=True)
def default(self):
Log.info(self, "This command is deprecated."
" You can use this command instead, " +
Log.ENDC + Log.BOLD + "\n`wo debug --import-slow-log`" +
Log.ENDC)
def load(app):
# register the plugin class.. this only happens if the plugin is enabled
handler.register(WOImportslowlogController)
# register a hook (function) to run after arguments are parsed.
hook.register('post_argument_parsing', wo_import_slow_log_hook)

289
wo/cli/plugins/info.py Normal file
View File

@@ -0,0 +1,289 @@
"""WOInfo Plugin for WordOps"""
from cement.core.controller import CementBaseController, expose
from cement.core import handler, hook
from wo.core.variables import WOVariables
from pynginxconfig import NginxConfig
from wo.core.aptget import WOAptGet
from wo.core.shellexec import WOShellExec
from wo.core.logging import Log
import os
import configparser
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 Nginx,'
' PHP and MySQL')
arguments = [
(['--mysql'],
dict(help='Get MySQL configuration information',
action='store_true')),
(['--php'],
dict(help='Get PHP configuration information',
action='store_true')),
(['--php7'],
dict(help='Get PHP 7.0 configuration information',
action='store_true')),
(['--nginx'],
dict(help='Get Nginx configuration information',
action='store_true')),
]
usage = "wo info [options]"
@expose(hide=True)
def info_nginx(self):
"""Display Nginx information"""
version = os.popen("nginx -v 2>&1 | cut -d':' -f2 | cut -d' ' -f2 | "
"cut -d'/' -f2 | tr -d '\n'").read()
allow = os.popen("grep ^allow /etc/nginx/common/acl.conf | "
"cut -d' ' -f2 | cut -d';' -f1 | tr '\n' ' '").read()
nc = NginxConfig()
nc.loadf('/etc/nginx/nginx.conf')
user = nc.get('user')[1]
worker_processes = nc.get('worker_processes')[1]
worker_connections = nc.get([('events',), 'worker_connections'])[1]
keepalive_timeout = nc.get([('http',), 'keepalive_timeout'])[1]
fastcgi_read_timeout = nc.get([('http',),
'fastcgi_read_timeout'])[1]
client_max_body_size = nc.get([('http',),
'client_max_body_size'])[1]
data = dict(version=version, allow=allow, user=user,
worker_processes=worker_processes,
keepalive_timeout=keepalive_timeout,
worker_connections=worker_connections,
fastcgi_read_timeout=fastcgi_read_timeout,
client_max_body_size=client_max_body_size)
self.app.render((data), 'info_nginx.mustache')
@expose(hide=True)
def info_php(self):
"""Display PHP information"""
version = os.popen("{0} -v 2>/dev/null | head -n1 | cut -d' ' -f2 |".format("php5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php") +
" cut -d'+' -f1 | tr -d '\n'").read
config = configparser.ConfigParser()
config.read('/etc/{0}/fpm/php.ini'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5"))
expose_php = config['PHP']['expose_php']
memory_limit = config['PHP']['memory_limit']
post_max_size = config['PHP']['post_max_size']
upload_max_filesize = config['PHP']['upload_max_filesize']
max_execution_time = config['PHP']['max_execution_time']
config.read('/etc/{0}/fpm/pool.d/www.conf'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5"))
www_listen = config['www']['listen']
www_ping_path = config['www']['ping.path']
www_pm_status_path = config['www']['pm.status_path']
www_pm = config['www']['pm']
www_pm_max_requests = config['www']['pm.max_requests']
www_pm_max_children = config['www']['pm.max_children']
www_pm_start_servers = config['www']['pm.start_servers']
www_pm_min_spare_servers = config['www']['pm.min_spare_servers']
www_pm_max_spare_servers = config['www']['pm.max_spare_servers']
www_request_terminate_time = (config['www']
['request_terminate_timeout'])
try:
www_xdebug = (config['www']['php_admin_flag[xdebug.profiler_enable'
'_trigger]'])
except Exception as e:
www_xdebug = 'off'
config.read('/etc/{0}/fpm/pool.d/debug.conf'.format("php/5.6" if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic') else "php5"))
debug_listen = config['debug']['listen']
debug_ping_path = config['debug']['ping.path']
debug_pm_status_path = config['debug']['pm.status_path']
debug_pm = config['debug']['pm']
debug_pm_max_requests = config['debug']['pm.max_requests']
debug_pm_max_children = config['debug']['pm.max_children']
debug_pm_start_servers = config['debug']['pm.start_servers']
debug_pm_min_spare_servers = config['debug']['pm.min_spare_servers']
debug_pm_max_spare_servers = config['debug']['pm.max_spare_servers']
debug_request_terminate = (config['debug']
['request_terminate_timeout'])
try:
debug_xdebug = (config['debug']['php_admin_flag[xdebug.profiler_'
'enable_trigger]'])
except Exception as e:
debug_xdebug = 'off'
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=www_listen, www_ping_path=www_ping_path,
www_pm_status_path=www_pm_status_path, www_pm=www_pm,
www_pm_max_requests=www_pm_max_requests,
www_pm_max_children=www_pm_max_children,
www_pm_start_servers=www_pm_start_servers,
www_pm_min_spare_servers=www_pm_min_spare_servers,
www_pm_max_spare_servers=www_pm_max_spare_servers,
www_request_terminate_timeout=www_request_terminate_time,
www_xdebug_profiler_enable_trigger=www_xdebug,
debug_listen=debug_listen, debug_ping_path=debug_ping_path,
debug_pm_status_path=debug_pm_status_path,
debug_pm=debug_pm,
debug_pm_max_requests=debug_pm_max_requests,
debug_pm_max_children=debug_pm_max_children,
debug_pm_start_servers=debug_pm_start_servers,
debug_pm_min_spare_servers=debug_pm_min_spare_servers,
debug_pm_max_spare_servers=debug_pm_max_spare_servers,
debug_request_terminate_timeout=debug_request_terminate,
debug_xdebug_profiler_enable_trigger=debug_xdebug)
self.app.render((data), 'info_php.mustache')
@expose(hide=True)
def info_php7(self):
"""Display PHP information"""
version = os.popen("php7.0 -v 2>/dev/null | head -n1 | cut -d' ' -f2 |"
" cut -d'+' -f1 | tr -d '\n'").read
config = configparser.ConfigParser()
config.read('/etc/php/7.0/fpm/php.ini')
expose_php = config['PHP']['expose_php']
memory_limit = config['PHP']['memory_limit']
post_max_size = config['PHP']['post_max_size']
upload_max_filesize = config['PHP']['upload_max_filesize']
max_execution_time = config['PHP']['max_execution_time']
config.read('/etc/php/7.0/fpm/pool.d/www.conf')
www_listen = config['www']['listen']
www_ping_path = config['www']['ping.path']
www_pm_status_path = config['www']['pm.status_path']
www_pm = config['www']['pm']
www_pm_max_requests = config['www']['pm.max_requests']
www_pm_max_children = config['www']['pm.max_children']
www_pm_start_servers = config['www']['pm.start_servers']
www_pm_min_spare_servers = config['www']['pm.min_spare_servers']
www_pm_max_spare_servers = config['www']['pm.max_spare_servers']
www_request_terminate_time = (config['www']
['request_terminate_timeout'])
try:
www_xdebug = (config['www']['php_admin_flag[xdebug.profiler_enable'
'_trigger]'])
except Exception as e:
www_xdebug = 'off'
config.read('/etc/php/7.0/fpm/pool.d/debug.conf')
debug_listen = config['debug']['listen']
debug_ping_path = config['debug']['ping.path']
debug_pm_status_path = config['debug']['pm.status_path']
debug_pm = config['debug']['pm']
debug_pm_max_requests = config['debug']['pm.max_requests']
debug_pm_max_children = config['debug']['pm.max_children']
debug_pm_start_servers = config['debug']['pm.start_servers']
debug_pm_min_spare_servers = config['debug']['pm.min_spare_servers']
debug_pm_max_spare_servers = config['debug']['pm.max_spare_servers']
debug_request_terminate = (config['debug']
['request_terminate_timeout'])
try:
debug_xdebug = (config['debug']['php_admin_flag[xdebug.profiler_'
'enable_trigger]'])
except Exception as e:
debug_xdebug = 'off'
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=www_listen, www_ping_path=www_ping_path,
www_pm_status_path=www_pm_status_path, www_pm=www_pm,
www_pm_max_requests=www_pm_max_requests,
www_pm_max_children=www_pm_max_children,
www_pm_start_servers=www_pm_start_servers,
www_pm_min_spare_servers=www_pm_min_spare_servers,
www_pm_max_spare_servers=www_pm_max_spare_servers,
www_request_terminate_timeout=www_request_terminate_time,
www_xdebug_profiler_enable_trigger=www_xdebug,
debug_listen=debug_listen, debug_ping_path=debug_ping_path,
debug_pm_status_path=debug_pm_status_path,
debug_pm=debug_pm,
debug_pm_max_requests=debug_pm_max_requests,
debug_pm_max_children=debug_pm_max_children,
debug_pm_start_servers=debug_pm_start_servers,
debug_pm_min_spare_servers=debug_pm_min_spare_servers,
debug_pm_max_spare_servers=debug_pm_max_spare_servers,
debug_request_terminate_timeout=debug_request_terminate,
debug_xdebug_profiler_enable_trigger=debug_xdebug)
self.app.render((data), 'info_php.mustache')
@expose(hide=True)
def info_mysql(self):
"""Display MySQL information"""
version = os.popen("mysql -V | awk '{print($5)}' | cut -d ',' "
"-f1 | tr -d '\n'").read()
host = "localhost"
port = os.popen("mysql -e \"show variables\" | grep ^port | awk "
"'{print($2)}' | tr -d '\n'").read()
wait_timeout = os.popen("mysql -e \"show variables\" | grep "
"^wait_timeout | awk '{print($2)}' | "
"tr -d '\n'").read()
interactive_timeout = os.popen("mysql -e \"show variables\" | grep "
"^interactive_timeout | awk "
"'{print($2)}' | tr -d '\n'").read()
max_used_connections = os.popen("mysql -e \"show global status\" | "
"grep Max_used_connections | awk "
"'{print($2)}' | tr -d '\n'").read()
datadir = os.popen("mysql -e \"show variables\" | grep datadir | awk"
" '{print($2)}' | tr -d '\n'").read()
socket = os.popen("mysql -e \"show variables\" | 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"""
if (not self.app.pargs.nginx and not self.app.pargs.php
and not self.app.pargs.mysql and not self.app.pargs.php7):
self.app.pargs.nginx = True
self.app.pargs.php = True
self.app.pargs.mysql = True
if WOAptGet.is_installed(self, 'php7.0-fpm'):
self.app.pargs.php = True
if self.app.pargs.nginx:
if WOAptGet.is_installed(self, 'nginx-custom') or WOAptGet.is_installed(self, 'nginx-common'):
self.info_nginx()
else:
Log.error(self, "Nginx is not installed")
if self.app.pargs.php:
if (WOVariables.wo_platform_distro == 'debian' or WOVariables.wo_platform_codename == 'precise'):
if WOAptGet.is_installed(self, 'php5-fpm'):
self.info_php()
else:
Log.error(self, "PHP5 is not installed")
else:
if WOAptGet.is_installed(self, 'php5.6-fpm'):
self.info_php()
else:
Log.error(self, "PHP5.6 is not installed")
if self.app.pargs.php7:
if WOAptGet.is_installed(self, 'php7.0-fpm'):
self.info_php7()
else:
Log.error(self, "PHP 7.0 is not installed")
if self.app.pargs.mysql:
if WOShellExec.cmd_exec(self, "mysqladmin ping"):
self.info_mysql()
else:
Log.error(self, "MySQL is not installed")
def load(app):
# register the plugin class.. this only happens if the plugin is enabled
handler.register(WOInfoController)
# register a hook (function) to run after arguments are parsed.
hook.register('post_argument_parsing', wo_info_hook)

577
wo/cli/plugins/log.py Normal file
View File

@@ -0,0 +1,577 @@
"""Logfile Plugin for WordOps"""
from cement.core.controller import CementBaseController, expose
from cement.core import handler, hook
from wo.core.logging import Log
from wo.cli.plugins.site_functions import logwatch
from wo.core.variables import WOVariables
from wo.core.fileutils import WOFileUtils
from wo.core.shellexec import WOShellExec
from wo.core.sendmail import WOSendMail
from wo.core.mysql import WOMysql
import os
import glob
import gzip
def wo_log_hook(app):
pass
class WOLogController(CementBaseController):
class Meta:
label = 'log'
description = 'Perform operations on Nginx, PHP and MySQL log files'
stacked_on = 'base'
stacked_type = 'nested'
usage = "wo log [<site_name>] [options]"
@expose(hide=True)
def default(self):
self.app.args.print_help()
class WOLogShowController(CementBaseController):
class Meta:
label = 'show'
description = 'Show Nginx, PHP, MySQL log file'
stacked_on = 'log'
stacked_type = 'nested'
arguments = [
(['--all'],
dict(help='Show All logs file', action='store_true')),
(['--nginx'],
dict(help='Show Nginx Error logs file', action='store_true')),
(['--php'],
dict(help='Show PHP Error logs file', action='store_true')),
(['--fpm'],
dict(help='Show PHP5-fpm slow logs file',
action='store_true')),
(['--mysql'],
dict(help='Show MySQL logs file', action='store_true')),
(['--wp'],
dict(help='Show Site specific WordPress logs file',
action='store_true')),
(['--access'],
dict(help='Show Nginx access log file',
action='store_true')),
(['site_name'],
dict(help='Website Name', nargs='?', default=None))
]
usage = "wo log show [<site_name>] [options]"
@expose(hide=True)
def default(self):
"""Default function of log show"""
self.msg = []
if self.app.pargs.php:
self.app.pargs.nginx = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (not self.app.pargs.site_name)):
self.app.pargs.nginx = True
self.app.pargs.fpm = True
self.app.pargs.mysql = True
self.app.pargs.access = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (self.app.pargs.site_name)):
self.app.pargs.nginx = True
self.app.pargs.wp = True
self.app.pargs.access = True
self.app.pargs.mysql = True
if self.app.pargs.nginx and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*error.log"]
if self.app.pargs.access and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*access.log"]
if self.app.pargs.fpm:
open('/var/log/php5/slow.log', 'a').close()
open('/var/log/php5/fpm.log', 'a').close()
self.msg = self.msg + ['/var/log/php5/slow.log',
'/var/log/php5/fpm.log']
if self.app.pargs.mysql:
# MySQL debug will not work for remote MySQL
if WOVariables.wo_mysql_host is "localhost":
if os.path.isfile('/var/log/mysql/mysql-slow.log'):
self.msg = self.msg + ['/var/log/mysql/mysql-slow.log']
else:
Log.info(self, "MySQL slow-log not found, skipped")
else:
Log.warn(self, "Remote MySQL found, WordOps does not support"
"remote MySQL servers or log files")
if self.app.pargs.site_name:
webroot = "{0}{1}".format(WOVariables.wo_webroot,
self.app.pargs.site_name)
if not os.path.isdir(webroot):
Log.error(self, "Site not present, quitting")
if self.app.pargs.access:
self.msg = self.msg + ["{0}/{1}/logs/access.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.nginx:
self.msg = self.msg + ["{0}/{1}/logs/error.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.wp:
if os.path.isdir('{0}/htdocs/wp-content'.format(webroot)):
if not os.path.isfile('{0}/logs/debug.log'
.format(webroot)):
if not os.path.isfile('{0}/htdocs/wp-content/debug.log'
.format(webroot)):
open("{0}/htdocs/wp-content/debug.log"
.format(webroot),
encoding='utf-8', mode='a').close()
WOShellExec.cmd_exec(self, "chown {1}: {0}/htdocs/"
"wp-content/debug.log"
"".format(webroot,
WOVariables
.wo_php_user)
)
# create symbolic link for debug log
WOFileUtils.create_symlink(self, ["{0}/htdocs/wp-content/"
"debug.log"
.format(webroot),
'{0}/logs/debug.log'
.format(webroot)])
self.msg = self.msg + ["{0}/{1}/logs/debug.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
else:
Log.info(self, "Site is not WordPress site, skipping "
"WordPress logs")
watch_list = []
for w_list in self.msg:
watch_list = watch_list + glob.glob(w_list)
logwatch(self, watch_list)
class WOLogResetController(CementBaseController):
class Meta:
label = 'reset'
description = 'Reset Nginx, PHP, MySQL log file'
stacked_on = 'log'
stacked_type = 'nested'
arguments = [
(['--all'],
dict(help='Reset All logs file', action='store_true')),
(['--nginx'],
dict(help='Reset Nginx Error logs file', action='store_true')),
(['--php'],
dict(help='Reset PHP Error logs file', action='store_true')),
(['--fpm'],
dict(help='Reset PHP5-fpm slow logs file',
action='store_true')),
(['--mysql'],
dict(help='Reset MySQL logs file', action='store_true')),
(['--wp'],
dict(help='Reset Site specific WordPress logs file',
action='store_true')),
(['--access'],
dict(help='Reset Nginx access log file',
action='store_true')),
(['--slow-log-db'],
dict(help='Drop all rows from slowlog table in database',
action='store_true')),
(['site_name'],
dict(help='Website Name', nargs='?', default=None))
]
usage = "wo log reset [<site_name>] [options]"
@expose(hide=True)
def default(self):
"""Default function of log reset"""
self.msg = []
if self.app.pargs.php:
self.app.pargs.nginx = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (not self.app.pargs.site_name)
and (not self.app.pargs.slow_log_db)):
self.app.pargs.nginx = True
self.app.pargs.fpm = True
self.app.pargs.mysql = True
self.app.pargs.access = True
self.app.pargs.slow_log_db = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (self.app.pargs.site_name)
and (not self.app.pargs.slow-log-db)):
self.app.pargs.nginx = True
self.app.pargs.wp = True
self.app.pargs.access = True
self.app.pargs.mysql = True
if self.app.pargs.slow_log_db:
if os.path.isdir("/var/www/22222/htdocs/db/anemometer"):
Log.info(self, "Resetting MySQL slow_query_log database table")
WOMysql.execute(self, "TRUNCATE TABLE "
"slow_query_log.global_query_review_history")
WOMysql.execute(self, "TRUNCATE TABLE "
"slow_query_log.global_query_review")
if self.app.pargs.nginx and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*error.log"]
if self.app.pargs.access and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*access.log"]
if self.app.pargs.fpm:
open('/var/log/php5/slow.log', 'a').close()
open('/var/log/php5/fpm.log', 'a').close()
self.msg = self.msg + ['/var/log/php5/slow.log',
'/var/log/php5/fpm.log']
if self.app.pargs.mysql:
# MySQL debug will not work for remote MySQL
if WOVariables.wo_mysql_host is "localhost":
if os.path.isfile('/var/log/mysql/mysql-slow.log'):
self.msg = self.msg + ['/var/log/mysql/mysql-slow.log']
else:
Log.info(self, "MySQL slow-log not found, skipped")
else:
Log.warn(self, "Remote MySQL found, WordOps does not support"
"remote MySQL servers or log files")
if self.app.pargs.site_name:
webroot = "{0}{1}".format(WOVariables.wo_webroot,
self.app.pargs.site_name)
if not os.path.isdir(webroot):
Log.error(self, "Site not present, quitting")
if self.app.pargs.access:
self.msg = self.msg + ["{0}/{1}/logs/access.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.nginx:
self.msg = self.msg + ["{0}/{1}/logs/error.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.wp:
if os.path.isdir('{0}/htdocs/wp-content'.format(webroot)):
if not os.path.isfile('{0}/logs/debug.log'
.format(webroot)):
if not os.path.isfile('{0}/htdocs/wp-content/debug.log'
.format(webroot)):
open("{0}/htdocs/wp-content/debug.log"
.format(webroot),
encoding='utf-8', mode='a').close()
WOShellExec.cmd_exec(self, "chown {1}: {0}/htdocs/"
"wp-content/debug.log"
"".format(webroot,
WOVariables
.wo_php_user)
)
# create symbolic link for debug log
WOFileUtils.create_symlink(self, ["{0}/htdocs/wp-content/"
"debug.log"
.format(webroot),
'{0}/logs/debug.log'
.format(webroot)])
self.msg = self.msg + ["{0}/{1}/logs/debug.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
else:
Log.info(self, "Site is not WordPress site, skipping "
"WordPress logs")
reset_list = []
for r_list in self.msg:
reset_list = reset_list + glob.glob(r_list)
# Clearing content of file
for r_list in reset_list:
Log.info(self, "Resetting file {file}".format(file=r_list))
open(r_list, 'w').close()
class WOLogGzipController(CementBaseController):
class Meta:
label = 'gzip'
description = 'GZip Nginx, PHP, MySQL log file'
stacked_on = 'log'
stacked_type = 'nested'
arguments = [
(['--all'],
dict(help='GZip All logs file', action='store_true')),
(['--nginx'],
dict(help='GZip Nginx Error logs file', action='store_true')),
(['--php'],
dict(help='GZip PHP Error logs file', action='store_true')),
(['--fpm'],
dict(help='GZip PHP5-fpm slow logs file',
action='store_true')),
(['--mysql'],
dict(help='GZip MySQL logs file', action='store_true')),
(['--wp'],
dict(help='GZip Site specific WordPress logs file',
action='store_true')),
(['--access'],
dict(help='GZip Nginx access log file',
action='store_true')),
(['site_name'],
dict(help='Website Name', nargs='?', default=None))
]
usage = "wo log gzip [<site_name>] [options]"
@expose(hide=True)
def default(self):
"""Default function of log GZip"""
self.msg = []
if self.app.pargs.php:
self.app.pargs.nginx = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (not self.app.pargs.site_name)):
self.app.pargs.nginx = True
self.app.pargs.fpm = True
self.app.pargs.mysql = True
self.app.pargs.access = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (self.app.pargs.site_name)):
self.app.pargs.nginx = True
self.app.pargs.wp = True
self.app.pargs.access = True
self.app.pargs.mysql = True
if self.app.pargs.nginx and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*error.log"]
if self.app.pargs.access and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*access.log"]
if self.app.pargs.fpm:
open('/var/log/php5/slow.log', 'a').close()
open('/var/log/php5/fpm.log', 'a').close()
self.msg = self.msg + ['/var/log/php5/slow.log',
'/var/log/php5/fpm.log']
if self.app.pargs.mysql:
# MySQL debug will not work for remote MySQL
if WOVariables.wo_mysql_host is "localhost":
if os.path.isfile('/var/log/mysql/mysql-slow.log'):
self.msg = self.msg + ['/var/log/mysql/mysql-slow.log']
else:
Log.info(self, "MySQL slow-log not found, skipped")
else:
Log.warn(self, "Remote MySQL found, WordOps does not support"
"remote MySQL servers or log files")
if self.app.pargs.site_name:
webroot = "{0}{1}".format(WOVariables.wo_webroot,
self.app.pargs.site_name)
if not os.path.isdir(webroot):
Log.error(self, "Site not present, quitting")
if self.app.pargs.access:
self.msg = self.msg + ["{0}/{1}/logs/access.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.nginx:
self.msg = self.msg + ["{0}/{1}/logs/error.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.wp:
if os.path.isdir('{0}/htdocs/wp-content'.format(webroot)):
if not os.path.isfile('{0}/logs/debug.log'
.format(webroot)):
if not os.path.isfile('{0}/htdocs/wp-content/debug.log'
.format(webroot)):
open("{0}/htdocs/wp-content/debug.log"
.format(webroot),
encoding='utf-8', mode='a').close()
WOShellExec.cmd_exec(self, "chown {1}: {0}/htdocs/"
"wp-content/debug.log"
"".format(webroot,
WOVariables
.wo_php_user)
)
# create symbolic link for debug log
WOFileUtils.create_symlink(self, ["{0}/htdocs/wp-content/"
"debug.log"
.format(webroot),
'{0}/logs/debug.log'
.format(webroot)])
self.msg = self.msg + ["{0}/{1}/logs/debug.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
else:
Log.info(self, "Site is not WordPress site, skipping "
"WordPress logs")
gzip_list = []
for g_list in self.msg:
gzip_list = gzip_list + glob.glob(g_list)
# Gzip content of file
for g_list in gzip_list:
Log.info(self, "Gzipping file {file}".format(file=g_list))
in_file = g_list
in_data = open(in_file, "rb").read()
out_gz = g_list + ".gz"
gzf = gzip.open(out_gz, "wb")
gzf.write(in_data)
gzf.close()
class WOLogMailController(CementBaseController):
class Meta:
label = 'mail'
description = 'Mail Nginx, PHP, MySQL log file'
stacked_on = 'log'
stacked_type = 'nested'
arguments = [
(['--all'],
dict(help='Mail All logs file', action='store_true')),
(['--nginx'],
dict(help='Mail Nginx Error logs file', action='store_true')),
(['--php'],
dict(help='Mail PHP Error logs file', action='store_true')),
(['--fpm'],
dict(help='Mail PHP5-fpm slow logs file',
action='store_true')),
(['--mysql'],
dict(help='Mail MySQL logs file', action='store_true')),
(['--wp'],
dict(help='Mail Site specific WordPress logs file',
action='store_true')),
(['--access'],
dict(help='Mail Nginx access log file',
action='store_true')),
(['site_name'],
dict(help='Website Name', nargs='?', default=None)),
(['--to'],
dict(help='Email addresses to send log files', action='append',
dest='to', nargs=1, required=True)),
]
usage = "wo log mail [<site_name>] [options]"
@expose(hide=True)
def default(self):
"""Default function of log Mail"""
self.msg = []
if self.app.pargs.php:
self.app.pargs.nginx = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (not self.app.pargs.site_name)):
self.app.pargs.nginx = True
self.app.pargs.fpm = True
self.app.pargs.mysql = True
self.app.pargs.access = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (self.app.pargs.site_name)):
self.app.pargs.nginx = True
self.app.pargs.wp = True
self.app.pargs.access = True
self.app.pargs.mysql = True
if self.app.pargs.nginx and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*error.log"]
if self.app.pargs.access and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*access.log"]
if self.app.pargs.fpm:
open('/var/log/php5/slow.log', 'a').close()
open('/var/log/php5/fpm.log', 'a').close()
self.msg = self.msg + ['/var/log/php5/slow.log',
'/var/log/php5/fpm.log']
if self.app.pargs.mysql:
# MySQL debug will not work for remote MySQL
if WOVariables.wo_mysql_host is "localhost":
if os.path.isfile('/var/log/mysql/mysql-slow.log'):
self.msg = self.msg + ['/var/log/mysql/mysql-slow.log']
else:
Log.info(self, "MySQL slow-log not found, skipped")
else:
Log.warn(self, "Remote MySQL found, WordOps does not support"
"remote MySQL servers or log files")
if self.app.pargs.site_name:
webroot = "{0}{1}".format(WOVariables.wo_webroot,
self.app.pargs.site_name)
if not os.path.isdir(webroot):
Log.error(self, "Site not present, quitting")
if self.app.pargs.access:
self.msg = self.msg + ["{0}/{1}/logs/access.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.nginx:
self.msg = self.msg + ["{0}/{1}/logs/error.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.wp:
if os.path.isdir('{0}/htdocs/wp-content'.format(webroot)):
if not os.path.isfile('{0}/logs/debug.log'
.format(webroot)):
if not os.path.isfile('{0}/htdocs/wp-content/debug.log'
.format(webroot)):
open("{0}/htdocs/wp-content/debug.log"
.format(webroot),
encoding='utf-8', mode='a').close()
WOShellExec.cmd_exec(self, "chown {1}: {0}/htdocs/"
"wp-content/debug.log"
"".format(webroot,
WOVariables
.wo_php_user)
)
# create symbolic link for debug log
WOFileUtils.create_symlink(self, ["{0}/htdocs/wp-content/"
"debug.log"
.format(webroot),
'{0}/logs/debug.log'
.format(webroot)])
self.msg = self.msg + ["{0}/{1}/logs/debug.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
else:
Log.info(self, "Site is not WordPress site, skipping "
"WordPress logs")
mail_list = []
for m_list in self.msg:
mail_list = mail_list + glob.glob(m_list)
for tomail in self.app.pargs.to:
Log.info(self, "Sending mail to {0}".format(tomail[0]))
WOSendMail("wordops", tomail[0], "{0} Log Files"
.format(WOVariables.wo_fqdn),
"Hi,\n The requested logfiles are attached."
"\n\nBest regards,\nYour WordOps worker",
files=mail_list, port=25, isTls=False)
def load(app):
# register the plugin class.. this only happens if the plugin is enabled
handler.register(WOLogController)
handler.register(WOLogShowController)
handler.register(WOLogResetController)
handler.register(WOLogGzipController)
handler.register(WOLogMailController)
# register a hook (function) to run after arguments are parsed.
hook.register('post_argument_parsing', wo_log_hook)

57
wo/cli/plugins/models.py Normal file
View File

@@ -0,0 +1,57 @@
from sqlalchemy import Column, DateTime, String, Integer, Boolean, func
from wo.core.database import Base
class SiteDB(Base):
"""
Database model for site table
"""
__tablename__ = 'sites'
__table_args__ = {'extend_existing': True}
id = Column(Integer, primary_key=True)
sitename = Column(String, unique=True)
site_type = Column(String)
cache_type = Column(String)
site_path = Column(String)
# Use default=func.now() to set the default created time
# of a site to be the current time when a
# Site record was created
created_on = Column(DateTime, default=func.now())
is_enabled = Column(Boolean, unique=False, default=True, nullable=False)
is_ssl = Column(Boolean, unique=False, default=False)
storage_fs = Column(String)
storage_db = Column(String)
db_name = Column(String)
db_user = Column(String)
db_password = Column(String)
db_host = Column(String)
is_hhvm = Column(Boolean, unique=False, default=False)
php_version = Column(String)
def __init__(self, sitename=None, site_type=None, cache_type=None,
site_path=None, site_enabled=None,
is_ssl=None, storage_fs=None, storage_db=None, db_name=None,
db_user=None, db_password=None, db_host='localhost',
hhvm=None, php_version=None):
self.sitename = sitename
self.site_type = site_type
self.cache_type = cache_type
self.site_path = site_path
self.is_enabled = site_enabled
self.is_ssl = is_ssl
self.storage_fs = storage_fs
self.storage_db = storage_db
self.db_name = db_name
self.db_user = db_user
self.db_password = db_password
self.db_host = db_host
self.is_hhvm = hhvm
self.php_version = php_version
# def __repr__(self):
# return '<Site %r>' % (self.site_type)
#
# def getType(self):
# return '%r>' % (self.site_type)

141
wo/cli/plugins/secure.py Normal file
View File

@@ -0,0 +1,141 @@
from cement.core.controller import CementBaseController, expose
from cement.core import handler, hook
from wo.core.aptget import WOAptGet
from wo.core.shellexec import WOShellExec
from wo.core.variables import WOVariables
from wo.core.logging import Log
from wo.core.git import WOGit
from wo.core.services import WOService
import string
import random
import sys
import hashlib
import getpass
def wo_secure_hook(app):
pass
class WOSecureController(CementBaseController):
class Meta:
label = 'secure'
stacked_on = 'base'
stacked_type = 'nested'
description = ('Secure command secure auth, ip and port')
arguments = [
(['--auth'],
dict(help='secure auth', action='store_true')),
(['--port'],
dict(help='secure port', action='store_true')),
(['--ip'],
dict(help='secure ip', action='store_true')),
(['user_input'],
dict(help='user input', nargs='?', default=None)),
(['user_pass'],
dict(help='user pass', nargs='?', default=None))]
usage = "wo secure [options]"
@expose(hide=True)
def default(self):
if self.app.pargs.auth:
self.secure_auth()
if self.app.pargs.port:
self.secure_port()
if self.app.pargs.ip:
self.secure_ip()
@expose(hide=True)
def secure_auth(self):
"""This function secures authentication"""
passwd = ''.join([random.choice
(string.ascii_letters + string.digits)
for n in range(6)])
if not self.app.pargs.user_input:
username = input("Provide HTTP authentication user "
"name [{0}] :".format(WOVariables.wo_user))
self.app.pargs.user_input = username
if username == "":
self.app.pargs.user_input = WOVariables.wo_user
if not self.app.pargs.user_pass:
password = getpass.getpass("Provide HTTP authentication "
"password [{0}] :".format(passwd))
self.app.pargs.user_pass = password
if password == "":
self.app.pargs.user_pass = passwd
Log.debug(self, "printf username:"
"$(openssl passwd -crypt "
"password 2> /dev/null)\n\""
"> /etc/nginx/htpasswd-wo 2>/dev/null")
WOShellExec.cmd_exec(self, "printf \"{username}:"
"$(openssl passwd -crypt "
"{password} 2> /dev/null)\n\""
"> /etc/nginx/htpasswd-wo 2>/dev/null"
.format(username=self.app.pargs.user_input,
password=self.app.pargs.user_pass),
log=False)
WOGit.add(self, ["/etc/nginx"],
msg="Adding changed secure auth into Git")
@expose(hide=True)
def secure_port(self):
"""This function Secures port"""
if self.app.pargs.user_input:
while not self.app.pargs.user_input.isdigit():
Log.info(self, "Please enter a valid port number ")
self.app.pargs.user_input = input("WordOps "
"admin port [22222]:")
if not self.app.pargs.user_input:
port = input("WordOps admin port [22222]:")
if port == "":
self.app.pargs.user_input = 22222
while not port.isdigit() and port != "":
Log.info(self, "Please Enter valid port number :")
port = input("WordOps admin port [22222]:")
self.app.pargs.user_input = port
if WOVariables.wo_platform_distro == 'ubuntu':
WOShellExec.cmd_exec(self, "sed -i \"s/listen.*/listen "
"{port} default_server ssl http2;/\" "
"/etc/nginx/sites-available/22222"
.format(port=self.app.pargs.user_input))
if WOVariables.wo_platform_distro == 'debian':
WOShellExec.cmd_exec(self, "sed -i \"s/listen.*/listen "
"{port} default_server ssl http2;/\" "
"/etc/nginx/sites-available/22222"
.format(port=self.app.pargs.user_input))
WOGit.add(self, ["/etc/nginx"],
msg="Adding changed secure port into Git")
if not WOService.reload_service(self, 'nginx'):
Log.error(self, "service nginx reload failed. "
"check issues with `nginx -t` command")
Log.info(self, "Successfully port changed {port}"
.format(port=self.app.pargs.user_input))
@expose(hide=True)
def secure_ip(self):
"""IP whitelisting"""
newlist = []
if not self.app.pargs.user_input:
ip = input("Enter the comma separated IP addresses "
"to white list [127.0.0.1]:")
self.app.pargs.user_input = ip
try:
user_ip = self.app.pargs.user_input.split(',')
except Exception as e:
user_ip = ['127.0.0.1']
for ip_addr in user_ip:
if not ("exist_ip_address "+ip_addr in open('/etc/nginx/common/'
'acl.conf').read()):
WOShellExec.cmd_exec(self, "sed -i "
"\"/deny/i allow {whitelist_address}\;\""
" /etc/nginx/common/acl.conf"
.format(whitelist_address=ip_addr))
WOGit.add(self, ["/etc/nginx"],
msg="Adding changed secure ip into Git")
Log.info(self, "Successfully added IP address in acl.conf file")
def load(app):
handler.register(WOSecureController)
hook.register('post_argument_parsing', wo_secure_hook)

1735
wo/cli/plugins/site.py Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

126
wo/cli/plugins/sitedb.py Normal file
View File

@@ -0,0 +1,126 @@
from sqlalchemy import Column, DateTime, String, Integer, Boolean
from sqlalchemy import ForeignKey, func
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base
from wo.core.logging import Log
from wo.core.database import db_session
from wo.cli.plugins.models import SiteDB
import sys
import glob
def addNewSite(self, site, stype, cache, path,
enabled=True, ssl=False, fs='ext4', db='mysql',
db_name=None, db_user=None, db_password=None,
db_host='localhost', hhvm=0, php_version='5.5'):
"""
Add New Site record information into the wo database.
"""
try:
newRec = SiteDB(site, stype, cache, path, enabled, ssl, fs, db,
db_name, db_user, db_password, db_host, hhvm,
php_version)
db_session.add(newRec)
db_session.commit()
except Exception as e:
Log.debug(self, "{0}".format(e))
Log.error(self, "Unable to add site to database")
def getSiteInfo(self, site):
"""
Retrieves site record from ee databse
"""
try:
q = SiteDB.query.filter(SiteDB.sitename == site).first()
return q
except Exception as e:
Log.debug(self, "{0}".format(e))
Log.error(self, "Unable to query database for site info")
def updateSiteInfo(self, site, stype='', cache='', webroot='',
enabled=True, ssl=False, fs='', db='', db_name=None,
db_user=None, db_password=None, db_host=None, hhvm=None,
php_version=''):
"""updates site record in database"""
try:
q = SiteDB.query.filter(SiteDB.sitename == site).first()
except Exception as e:
Log.debug(self, "{0}".format(e))
Log.error(self, "Unable to query database for site info")
if not q:
Log.error(self, "{0} does not exist in database".format(site))
# Check if new record matches old if not then only update database
if stype and q.site_type != stype:
q.site_type = stype
if cache and q.cache_type != cache:
q.cache_type = cache
if q.is_enabled != enabled:
q.is_enabled = enabled
if q.is_ssl != ssl:
q.is_ssl = ssl
if db_name and q.db_name != db_name:
q.db_name = db_name
if db_user and q.db_user != db_user:
q.db_user = db_user
if db_user and q.db_password != db_password:
q.db_password = db_password
if db_host and q.db_host != db_host:
q.db_host = db_host
if webroot and q.site_path != webroot:
q.site_path = webroot
if (hhvm is not None) and (q.is_hhvm is not hhvm):
q.is_hhvm = hhvm
if php_version and q.php_version != php_version:
q.php_version = php_version
try:
q.created_on = func.now()
db_session.commit()
except Exception as e:
Log.debug(self, "{0}".format(e))
Log.error(self, "Unable to update site info in application database.")
def deleteSiteInfo(self, site):
"""Delete site record in database"""
try:
q = SiteDB.query.filter(SiteDB.sitename == site).first()
except Exception as e:
Log.debug(self, "{0}".format(e))
Log.error(self, "Unable to query database")
if not q:
Log.error(self, "{0} does not exist in database".format(site))
try:
db_session.delete(q)
db_session.commit()
except Exception as e:
Log.debug(self, "{0}".format(e))
Log.error(self, "Unable to delete site from application database.")
def getAllsites(self):
"""
1. returns all records from ee database
"""
try:
q = SiteDB.query.all()
return q
except Exception as e:
Log.debug(self, "{0}".format(e))
Log.error(self, "Unable to query database")

2047
wo/cli/plugins/stack.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,115 @@
from cement.core.controller import CementBaseController, expose
from cement.core import handler, hook
from wo.core.mysql import WOMysql
from wo.core.logging import Log
from wo.core.variables import WOVariables
from wo.core.aptget import WOAptGet
from wo.core.shellexec import WOShellExec
from wo.core.apt_repo import WORepo
from wo.core.services import WOService
import configparser
import os
class WOStackMigrateController(CementBaseController):
class Meta:
label = 'migrate'
stacked_on = 'stack'
stacked_type = 'nested'
description = ('Migrate stack safely')
arguments = [
(['--mariadb'],
dict(help="Migrate database to MariaDB",
action='store_true')),
]
@expose(hide=True)
def migrate_mariadb(self):
# Backup all database
WOMysql.backupAll(self)
# Add MariaDB repo
Log.info(self, "Adding repository for MariaDB, please wait...")
mysql_pref = ("Package: *\nPin: origin sfo1.mirrors.digitalocean.com"
"\nPin-Priority: 1000\n")
with open('/etc/apt/preferences.d/'
'MariaDB.pref', 'w') as mysql_pref_file:
mysql_pref_file.write(mysql_pref)
WORepo.add(self, repo_url=WOVariables.wo_mysql_repo)
Log.debug(self, 'Adding key for {0}'
.format(WOVariables.wo_mysql_repo))
WORepo.add_key(self, '0xcbcb082a1bb943db',
keyserver="keyserver.ubuntu.com")
config = configparser.ConfigParser()
if os.path.exists('/etc/mysql/conf.d/my.cnf'):
config.read('/etc/mysql/conf.d/my.cnf')
else:
config.read(os.path.expanduser("~")+'/.my.cnf')
try:
chars = config['client']['password']
except Exception as e:
Log.error(self, "Error: process exited with error %s"
% e)
Log.debug(self, "Pre-seeding MariaDB")
Log.debug(self, "echo \"mariadb-server-10.0 "
"mysql-server/root_password "
"password \" | "
"debconf-set-selections")
WOShellExec.cmd_exec(self, "echo \"mariadb-server-10.0 "
"mysql-server/root_password "
"password {chars}\" | "
"debconf-set-selections"
.format(chars=chars),
log=False)
Log.debug(self, "echo \"mariadb-server-10.0 "
"mysql-server/root_password_again "
"password \" | "
"debconf-set-selections")
WOShellExec.cmd_exec(self, "echo \"mariadb-server-10.0 "
"mysql-server/root_password_again "
"password {chars}\" | "
"debconf-set-selections"
.format(chars=chars),
log=False)
# Install MariaDB
apt_packages = WOVariables.wo_mysql
# If PHP is installed then install php5-mysql
if WOAptGet.is_installed(self, "php5-fpm"):
apt_packages = apt_packages + ["php5-mysql"]
Log.info(self, "Updating apt-cache, hang on...")
WOAptGet.update(self)
Log.info(self, "Installing MariaDB, hang on...")
WOAptGet.remove(self, ["mysql-common", "libmysqlclient18"])
WOAptGet.auto_remove(self)
WOAptGet.install(self, apt_packages)
@expose(hide=True)
def default(self):
if ((not self.app.pargs.mariadb)):
self.app.args.print_help()
if self.app.pargs.mariadb:
if WOVariables.wo_mysql_host is not "localhost":
Log.error(self, "Remote MySQL server in use, skipping local install")
if WOShellExec.cmd_exec(self, "mysqladmin ping") and (not
WOAptGet.is_installed(self, 'mariadb-server')):
Log.info(self, "If your database size is big, "
"migration may take some time.")
Log.info(self, "During migration non nginx-cached parts of "
"your site may remain down")
start_migrate = input("Type \"mariadb\" to continue:")
if start_migrate != "mariadb":
Log.error(self, "Not starting migration")
self.migrate_mariadb()
else:
Log.error(self, "Your current MySQL is not alive or "
"you allready installed MariaDB")

View File

@@ -0,0 +1,403 @@
from cement.core.controller import CementBaseController, expose
from cement.core import handler, hook
from wo.core.services import WOService
from wo.core.logging import Log
from wo.core.variables import WOVariables
from wo.core.aptget import WOAptGet
class WOStackStatusController(CementBaseController):
class Meta:
label = 'stack_services'
stacked_on = 'stack'
stacked_type = 'embedded'
description = 'Check the stack status'
arguments = [
(['--memcache'],
dict(help='start/stop/restart memcache', action='store_true')),
]
@expose(help="Start stack services")
def start(self):
"""Start services"""
services = []
if not (self.app.pargs.nginx or self.app.pargs.php or self.app.pargs.php7
or self.app.pargs.mysql or self.app.pargs.hhvm or self.app.pargs.memcache
or self.app.pargs.redis):
self.app.pargs.nginx = True
self.app.pargs.php = True
self.app.pargs.mysql = True
if self.app.pargs.nginx:
if WOAptGet.is_installed(self, 'nginx-custom') or WOAptGet.is_installed(self,'nginx-mainline'):
services = services + ['nginx']
else:
Log.info(self, "Nginx is not installed")
if self.app.pargs.php:
if (WOVariables.wo_platform_distro == 'debian' or WOVariables.wo_platform_codename == 'precise'):
if WOAptGet.is_installed(self, 'php5-fpm'):
services = services + ['php5-fpm']
else:
Log.info(self, "PHP5-FPM is not installed")
else:
if WOAptGet.is_installed(self, 'php5.6-fpm'):
services = services + ['php5.6-fpm']
else:
Log.info(self, "PHP5.6-FPM is not installed")
if WOAptGet.is_installed(self, 'php7.0-fpm'):
services = services + ['php7.0-fpm']
else:
Log.info(self, "PHP7.0-FPM is not installed")
if self.app.pargs.php7:
if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic'):
if WOAptGet.is_installed(self, 'php7.0-fpm'):
services = services + ['php7.0-fpm']
else:
Log.info(self, "PHP7.0-FPM is not installed")
else:
Log.info(self, "Your platform does not support PHP 7")
if self.app.pargs.mysql:
if ((WOVariables.wo_mysql_host is "localhost") or
(WOVariables.wo_mysql_host is "127.0.0.1")):
if (WOAptGet.is_installed(self, 'mysql-server') or
WOAptGet.is_installed(self, 'percona-server-server-5.6') or
WOAptGet.is_installed(self, 'mariadb-server')):
services = services + ['mysql']
else:
Log.info(self, "MySQL is not installed")
else:
Log.warn(self, "Remote MySQL found, "
"Unable to check MySQL service status")
if self.app.pargs.hhvm:
if WOAptGet.is_installed(self, 'hhvm'):
services = services + ['hhvm']
else:
Log.info(self, "HHVM is not installed")
if self.app.pargs.memcache:
if WOAptGet.is_installed(self, 'memcached'):
services = services + ['memcached']
else:
Log.info(self, "Memcache is not installed")
if self.app.pargs.redis:
if WOAptGet.is_installed(self, 'redis-server'):
services = services + ['redis-server']
else:
Log.info(self, "Redis server is not installed")
for service in services:
Log.debug(self, "Starting service: {0}".format(service))
WOService.start_service(self, service)
@expose(help="Stop stack services")
def stop(self):
"""Stop services"""
services = []
if not (self.app.pargs.nginx or self.app.pargs.php or self.app.pargs.php7
or self.app.pargs.mysql or self.app.pargs.hhvm or self.app.pargs.memcache
or self.app.pargs.redis):
self.app.pargs.nginx = True
self.app.pargs.php = True
self.app.pargs.mysql = True
if self.app.pargs.nginx:
if WOAptGet.is_installed(self, 'nginx-custom') or WOAptGet.is_installed(self,'nginx-mainline'):
services = services + ['nginx']
else:
Log.info(self, "Nginx is not installed")
if self.app.pargs.php:
if (WOVariables.wo_platform_distro == 'debian' or WOVariables.wo_platform_codename == 'precise'):
if WOAptGet.is_installed(self, 'php5-fpm'):
services = services + ['php5-fpm']
else:
Log.info(self, "PHP5-FPM is not installed")
else:
if WOAptGet.is_installed(self, 'php5.6-fpm'):
services = services + ['php5.6-fpm']
else:
Log.info(self, "PHP5.6-FPM is not installed")
if WOAptGet.is_installed(self, 'php7.0-fpm'):
services = services + ['php7.0-fpm']
else:
Log.info(self, "PHP7.0-FPM is not installed")
if self.app.pargs.php7:
if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic'):
if WOAptGet.is_installed(self, 'php7.0-fpm'):
services = services + ['php7.0-fpm']
else:
Log.info(self, "PHP7.0-FPM is not installed")
else:
Log.info(self, "Your platform does not support PHP 7")
if self.app.pargs.mysql:
if ((WOVariables.wo_mysql_host is "localhost") or
(WOVariables.wo_mysql_host is "127.0.0.1")):
if (WOAptGet.is_installed(self, 'mysql-server') or
WOAptGet.is_installed(self, 'percona-server-server-5.6') or
WOAptGet.is_installed(self, 'mariadb-server')):
services = services + ['mysql']
else:
Log.info(self, "MySQL is not installed")
else:
Log.warn(self, "Remote MySQL found, "
"Unable to check MySQL service status")
if self.app.pargs.hhvm:
if WOAptGet.is_installed(self, 'hhvm'):
services = services + ['hhvm']
else:
Log.info(self, "HHVM is not installed")
if self.app.pargs.memcache:
if WOAptGet.is_installed(self, 'memcached'):
services = services + ['memcached']
else:
Log.info(self, "Memcache is not installed")
if self.app.pargs.redis:
if WOAptGet.is_installed(self, 'redis-server'):
services = services + ['redis-server']
else:
Log.info(self, "Redis server is not installed")
for service in services:
Log.debug(self, "Stopping service: {0}".format(service))
WOService.stop_service(self, service)
@expose(help="Restart stack services")
def restart(self):
"""Restart services"""
services = []
if not (self.app.pargs.nginx or self.app.pargs.php or self.app.pargs.php7
or self.app.pargs.mysql or self.app.pargs.hhvm or self.app.pargs.memcache
or self.app.pargs.redis):
self.app.pargs.nginx = True
self.app.pargs.php = True
self.app.pargs.mysql = True
if self.app.pargs.nginx:
if WOAptGet.is_installed(self, 'nginx-custom') or WOAptGet.is_installed(self,'nginx-mainline'):
services = services + ['nginx']
else:
Log.info(self, "Nginx is not installed")
if self.app.pargs.php:
if (WOVariables.wo_platform_distro == 'debian' or WOVariables.wo_platform_codename == 'precise'):
if WOAptGet.is_installed(self, 'php5-fpm'):
services = services + ['php5-fpm']
else:
Log.info(self, "PHP5-FPM is not installed")
else:
if WOAptGet.is_installed(self, 'php5.6-fpm'):
services = services + ['php5.6-fpm']
else:
Log.info(self, "PHP5.6-FPM is not installed")
if WOAptGet.is_installed(self, 'php7.0-fpm'):
services = services + ['php7.0-fpm']
else:
Log.info(self, "PHP7.0-FPM is not installed")
if self.app.pargs.php7:
if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic'):
if WOAptGet.is_installed(self, 'php7.0-fpm'):
services = services + ['php7.0-fpm']
else:
Log.info(self, "PHP7.0-FPM is not installed")
else:
Log.info(self, "Your platform does not support PHP 7")
if self.app.pargs.mysql:
if ((WOVariables.wo_mysql_host is "localhost") or
(WOVariables.wo_mysql_host is "127.0.0.1")):
if (WOAptGet.is_installed(self, 'mysql-server') or
WOAptGet.is_installed(self, 'percona-server-server-5.6') or
WOAptGet.is_installed(self, 'mariadb-server')):
services = services + ['mysql']
else:
Log.info(self, "MySQL is not installed")
else:
Log.warn(self, "Remote MySQL found, "
"Unable to check MySQL service status")
if self.app.pargs.hhvm:
if WOAptGet.is_installed(self, 'hhvm'):
services = services + ['hhvm']
else:
Log.info(self, "HHVM is not installed")
if self.app.pargs.memcache:
if WOAptGet.is_installed(self, 'memcached'):
services = services + ['memcached']
else:
Log.info(self, "Memcache is not installed")
if self.app.pargs.redis:
if WOAptGet.is_installed(self, 'redis-server'):
services = services + ['redis-server']
else:
Log.info(self, "Redis server is not installed")
for service in services:
Log.debug(self, "Restarting service: {0}".format(service))
WOService.restart_service(self, service)
@expose(help="Get stack status")
def status(self):
"""Status of services"""
services = []
if not (self.app.pargs.nginx or self.app.pargs.php or self.app.pargs.php7
or self.app.pargs.mysql or self.app.pargs.hhvm or self.app.pargs.memcache
or self.app.pargs.redis):
self.app.pargs.nginx = True
self.app.pargs.php = True
self.app.pargs.mysql = True
self.app.pargs.hhvm = True
if self.app.pargs.nginx:
if WOAptGet.is_installed(self, 'nginx-custom') or WOAptGet.is_installed(self,'nginx-mainline'):
services = services + ['nginx']
else:
Log.info(self, "Nginx is not installed")
if self.app.pargs.php:
if (WOVariables.wo_platform_distro == 'debian' or WOVariables.wo_platform_codename == 'precise'):
if WOAptGet.is_installed(self, 'php5-fpm'):
services = services + ['php5-fpm']
else:
Log.info(self, "PHP5-FPM is not installed")
else:
if WOAptGet.is_installed(self, 'php5.6-fpm'):
services = services + ['php5.6-fpm']
else:
Log.info(self, "PHP5.6-FPM is not installed")
if WOAptGet.is_installed(self, 'php7.0-fpm'):
services = services + ['php7.0-fpm']
else:
Log.info(self, "PHP7.0-FPM is not installed")
if self.app.pargs.php7:
if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic'):
if WOAptGet.is_installed(self, 'php7.0-fpm'):
services = services + ['php7.0-fpm']
else:
Log.info(self, "PHP7.0-FPM is not installed")
else:
Log.info(self, "Your platform does not support PHP 7")
if self.app.pargs.mysql:
if ((WOVariables.wo_mysql_host is "localhost") or
(WOVariables.wo_mysql_host is "127.0.0.1")):
if (WOAptGet.is_installed(self, 'mysql-server') or
WOAptGet.is_installed(self, 'percona-server-server-5.6') or
WOAptGet.is_installed(self, 'mariadb-server')):
services = services + ['mysql']
else:
Log.info(self, "MySQL is not installed")
else:
Log.warn(self, "Remote MySQL found, "
"Unable to check MySQL service status")
if self.app.pargs.hhvm:
if WOAptGet.is_installed(self, 'hhvm'):
services = services + ['hhvm']
else:
Log.info(self, "HHVM is not installed")
if self.app.pargs.memcache:
if WOAptGet.is_installed(self, 'memcached'):
services = services + ['memcached']
else:
Log.info(self, "Memcache is not installed")
if self.app.pargs.redis:
if WOAptGet.is_installed(self, 'redis-server'):
services = services + ['redis-server']
else:
Log.info(self, "Redis server is not installed")
for service in services:
if WOService.get_service_status(self, service):
Log.info(self, "{0:10}: {1}".format(service, "Running"))
@expose(help="Reload stack services")
def reload(self):
"""Reload service"""
services = []
if not (self.app.pargs.nginx or self.app.pargs.php or self.app.pargs.php7
or self.app.pargs.mysql or self.app.pargs.hhvm or self.app.pargs.memcache
or self.app.pargs.redis):
self.app.pargs.nginx = True
self.app.pargs.php = True
self.app.pargs.mysql = True
if self.app.pargs.nginx:
if WOAptGet.is_installed(self, 'nginx-custom') or WOAptGet.is_installed(self,'nginx-mainline'):
services = services + ['nginx']
else:
Log.info(self, "Nginx is not installed")
if self.app.pargs.php:
if (WOVariables.wo_platform_distro == 'debian' or WOVariables.wo_platform_codename == 'precise'):
if WOAptGet.is_installed(self, 'php5-fpm'):
services = services + ['php5-fpm']
else:
Log.info(self, "PHP5-FPM is not installed")
else:
if WOAptGet.is_installed(self, 'php5.6-fpm'):
services = services + ['php5.6-fpm']
else:
Log.info(self, "PHP5.6-FPM is not installed")
if WOAptGet.is_installed(self, 'php7.0-fpm'):
services = services + ['php7.0-fpm']
else:
Log.info(self, "PHP7.0-FPM is not installed")
if self.app.pargs.php7:
if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic'):
if WOAptGet.is_installed(self, 'php7.0-fpm'):
services = services + ['php7.0-fpm']
else:
Log.info(self, "PHP7.0-FPM is not installed")
else:
Log.info(self, "Your platform does not support PHP 7")
if self.app.pargs.mysql:
if ((WOVariables.wo_mysql_host is "localhost") or
(WOVariables.wo_mysql_host is "127.0.0.1")):
if (WOAptGet.is_installed(self, 'mysql-server') or
WOAptGet.is_installed(self, 'percona-server-server-5.6') or
WOAptGet.is_installed(self, 'mariadb-server')):
services = services + ['mysql']
else:
Log.info(self, "MySQL is not installed")
else:
Log.warn(self, "Remote MySQL found, "
"Unable to check MySQL service status")
if self.app.pargs.hhvm:
Log.info(self, "HHVM does not support to reload")
if self.app.pargs.memcache:
if WOAptGet.is_installed(self, 'memcached'):
services = services + ['memcached']
else:
Log.info(self, "Memcache is not installed")
if self.app.pargs.redis:
if WOAptGet.is_installed(self, 'redis-server'):
services = services + ['redis-server']
else:
Log.info(self, "Redis server is not installed")
for service in services:
Log.debug(self, "Reloading service: {0}".format(service))
WOService.reload_service(self, service)

View File

@@ -0,0 +1,233 @@
from cement.core.controller import CementBaseController, expose
from cement.core import handler, hook
from wo.core.logging import Log
from wo.core.variables import WOVariables
from wo.core.aptget import WOAptGet
from wo.core.apt_repo import WORepo
from wo.core.services import WOService
from wo.core.fileutils import WOFileUtils
from wo.core.shellexec import WOShellExec
from wo.core.git import WOGit
from wo.core.download import WODownload
import configparser
import os
class WOStackUpgradeController(CementBaseController):
class Meta:
label = 'upgrade'
stacked_on = 'stack'
stacked_type = 'nested'
description = ('Upgrade stack safely')
arguments = [
(['--all'],
dict(help='Upgrade all stack', action='store_true')),
(['--web'],
dict(help='Upgrade web stack', action='store_true')),
(['--admin'],
dict(help='Upgrade admin tools stack', action='store_true')),
(['--nginx'],
dict(help='Upgrade Nginx stack', action='store_true')),
(['--nginxmainline'],
dict(help='Upgrade Nginx Mainline stack', action='store_true')),
(['--php'],
dict(help='Upgrade PHP stack', action='store_true')),
(['--mysql'],
dict(help='Upgrade MySQL stack', action='store_true')),
(['--hhvm'],
dict(help='Upgrade HHVM stack', action='store_true')),
(['--wpcli'],
dict(help='Upgrade WPCLI', action='store_true')),
(['--redis'],
dict(help='Upgrade Redis', action='store_true')),
(['--php56'],
dict(help="Upgrade to PHP5.6 from PHP5.5",
action='store_true')),
(['--no-prompt'],
dict(help="Upgrade Packages without any prompt",
action='store_true')),
]
@expose(hide=True)
def upgrade_php56(self):
if WOVariables.wo_platform_distro == "ubuntu":
if os.path.isfile("/etc/apt/sources.list.d/ondrej-php5-5_6-{0}."
"list".format(WOVariables.wo_platform_codename)):
Log.error(self, "Unable to find PHP 5.5")
else:
if not(os.path.isfile(WOVariables.wo_repo_file_path) and
WOFileUtils.grep(self, WOVariables.wo_repo_file_path,
"php55")):
Log.error(self, "Unable to find PHP 5.5")
Log.info(self, "During PHP update process non nginx-cached"
" parts of your site may remain down.")
# Check prompt
if (not self.app.pargs.no_prompt):
start_upgrade = input("Do you want to continue:[y/N]")
if start_upgrade != "Y" and start_upgrade != "y":
Log.error(self, "Not starting PHP package update")
if WOVariables.wo_platform_distro == "ubuntu":
WORepo.remove(self, ppa="ppa:ondrej/php5")
WORepo.add(self, ppa=WOVariables.wo_php_repo)
else:
WOAptGet.remove(self, ["php5-xdebug"])
WOFileUtils.searchreplace(self, WOVariables.wo_repo_file_path,
"php55", "php56")
Log.info(self, "Updating apt-cache, please wait...")
WOAptGet.update(self)
Log.info(self, "Installing packages, please wait ...")
if (WOVariables.wo_platform_codename == 'trusty' or WOVariables.wo_platform_codename == 'xenial' or WOVariables.wo_platform_codename == 'bionic'):
WOAptGet.install(self, WOVariables.wo_php5_6 + WOVariables.wo_php_extra)
else:
WOAptGet.install(self, WOVariables.wo_php)
if WOVariables.wo_platform_distro == "debian":
WOShellExec.cmd_exec(self, "pecl install xdebug")
with open("/etc/php5/mods-available/xdebug.ini",
encoding='utf-8', mode='a') as myfile:
myfile.write(";zend_extension=/usr/lib/php5/20131226/"
"xdebug.so\n")
WOFileUtils.create_symlink(self, ["/etc/php5/mods-available/"
"xdebug.ini", "/etc/php5/fpm/conf.d"
"/20-xedbug.ini"])
Log.info(self, "Successfully upgraded from PHP 5.5 to PHP 5.6")
@expose(hide=True)
def default(self):
# All package update
if ((not self.app.pargs.php56)):
apt_packages = []
packages = []
if ((not self.app.pargs.web) and (not self.app.pargs.nginx) and
(not self.app.pargs.php) and (not self.app.pargs.mysql) and
(not self.app.pargs.hhvm) and (not self.app.pargs.all) and
(not self.app.pargs.wpcli) and (not self.app.pargs.redis) and
(not self.app.pargs.nginxmainline)):
self.app.pargs.web = True
if self.app.pargs.all:
self.app.pargs.web = True
if self.app.pargs.web:
if WOAptGet.is_installed(self, 'nginx-custom'):
self.app.pargs.nginx = True
else:
Log.info(self, "Nginx is not already installed")
self.app.pargs.php = True
self.app.pargs.mysql = True
self.app.pargs.wpcli = True
if self.app.pargs.nginx :
if WOAptGet.is_installed(self, 'nginx-custom'):
apt_packages = apt_packages + WOVariables.wo_nginx
else:
Log.info(self, "Nginx Stable is not already installed")
if self.app.pargs.php:
if (WOVariables.wo_platform_distro == 'debian' or WOVariables.wo_platform_codename == 'precise'):
if WOAptGet.is_installed(self, 'php5-fpm'):
apt_packages = apt_packages + WOVariables.wo_php
else:
Log.info(self, "PHP is not installed")
if WOAptGet.is_installed(self, 'php7.0-fpm'):
apt_packages = apt_packages + WOVariables.wo_php7_0
else:
if WOAptGet.is_installed(self, 'php5.6-fpm'):
apt_packages = apt_packages + WOVariables.wo_php5_6 + WOVariables.wo_php_extra
else:
Log.info(self, "PHP 5.6 is not installed")
if WOAptGet.is_installed(self, 'php7.0-fpm'):
apt_packages = apt_packages + WOVariables.wo_php7_0 + WOVariables.wo_php_extra
else:
Log.info(self, "PHP 7.0 is not installed")
if self.app.pargs.hhvm:
if WOAptGet.is_installed(self, 'hhvm'):
apt_packages = apt_packages + WOVariables.wo_hhvm
else:
Log.info(self, "HHVM is not installed")
if self.app.pargs.mysql:
if WOAptGet.is_installed(self, 'mariadb-server'):
apt_packages = apt_packages + WOVariables.wo_mysql
else:
Log.info(self, "MariaDB is not installed")
if self.app.pargs.redis:
if WOAptGet.is_installed(self, 'redis-server'):
apt_packages = apt_packages + WOVariables.wo_redis
else:
Log.info(self, "Redis is not installed")
if self.app.pargs.wpcli:
if os.path.isfile('/usr/bin/wp'):
packages = packages + [["https://github.com/wp-cli/wp-cli/"
"releases/download/v{0}/"
"wp-cli-{0}.phar"
"".format(WOVariables.wo_wp_cli),
"/usr/bin/wp",
"WP-CLI"]]
else:
Log.info(self, "WPCLI is not installed with WordOps")
if len(packages) or len(apt_packages):
Log.info(self, "During package update process non nginx-cached"
" parts of your site may remain down")
# Check prompt
if (not self.app.pargs.no_prompt):
start_upgrade = input("Do you want to continue:[y/N]")
if start_upgrade != "Y" and start_upgrade != "y":
Log.error(self, "Not starting package update")
Log.info(self, "Updating packages, please wait...")
if len(apt_packages):
# apt-get update
WOAptGet.update(self)
# Update packages
WOAptGet.install(self, apt_packages)
# Post Actions after package updates
if (set(WOVariables.wo_nginx).issubset(set(apt_packages))):
WOService.restart_service(self, 'nginx')
if (WOVariables.wo_platform_distro == 'debian' or WOVariables.wo_platform_codename == 'precise'):
if set(WOVariables.wo_php).issubset(set(apt_packages)):
WOService.restart_service(self, 'php5-fpm')
else:
if set(WOVariables.wo_php5_6).issubset(set(apt_packages)):
WOService.restart_service(self, 'php5.6-fpm')
if set(WOVariables.wo_php7_0).issubset(set(apt_packages)):
WOService.restart_service(self, 'php7.0-fpm')
if set(WOVariables.wo_hhvm).issubset(set(apt_packages)):
WOService.restart_service(self, 'hhvm')
if set(WOVariables.wo_mysql).issubset(set(apt_packages)):
WOService.restart_service(self, 'mysql')
if set(WOVariables.wo_redis).issubset(set(apt_packages)):
WOService.restart_service(self, 'redis-server')
if len(packages):
if self.app.pargs.wpcli:
WOFileUtils.remove(self,['/usr/bin/wp'])
Log.debug(self, "Downloading following: {0}".format(packages))
WODownload.download(self, packages)
if self.app.pargs.wpcli:
WOFileUtils.chmod(self, "/usr/bin/wp", 0o775)
Log.info(self, "Successfully updated packages")
# PHP 5.6 to 5.6
elif (self.app.pargs.php56):
self.upgrade_php56()
else:
self.app.args.print_help()

94
wo/cli/plugins/sync.py Normal file
View File

@@ -0,0 +1,94 @@
from cement.core.controller import CementBaseController, expose
from cement.core import handler, hook
from wo.core.fileutils import WOFileUtils
from wo.cli.plugins.sitedb import *
from wo.core.mysql import *
from wo.core.logging import Log
def wo_sync_hook(app):
pass
class WOSyncController(CementBaseController):
class Meta:
label = 'sync'
stacked_on = 'base'
stacked_type = 'nested'
description = 'synchronize the WordOps database'
@expose(hide=True)
def default(self):
self.sync()
@expose(hide=True)
def sync(self):
"""
1. reads database information from wp/wo-config.php
2. updates records into wo database accordingly.
"""
Log.info(self, "Synchronizing wo database, please wait...")
sites = getAllsites(self)
if not sites:
pass
for site in sites:
if site.site_type in ['mysql', 'wp', 'wpsubdir', 'wpsubdomain']:
wo_site_webroot = site.site_path
# Read config files
configfiles = glob.glob(wo_site_webroot + '/*-config.php')
#search for wp-config.php inside htdocs/
if not configfiles:
Log.debug(self, "Config files not found in {0}/ "
.format(wo_site_webroot))
if site.site_type != 'mysql':
Log.debug(self, "Searching wp-config.php in {0}/htdocs/ "
.format(wo_site_webroot))
configfiles = glob.glob(wo_site_webroot + '/htdocs/wp-config.php')
if configfiles:
if WOFileUtils.isexist(self, configfiles[0]):
wo_db_name = (WOFileUtils.grep(self, configfiles[0],
'DB_NAME').split(',')[1]
.split(')')[0].strip().replace('\'', ''))
wo_db_user = (WOFileUtils.grep(self, configfiles[0],
'DB_USER').split(',')[1]
.split(')')[0].strip().replace('\'', ''))
wo_db_pass = (WOFileUtils.grep(self, configfiles[0],
'DB_PASSWORD').split(',')[1]
.split(')')[0].strip().replace('\'', ''))
wo_db_host = (WOFileUtils.grep(self, configfiles[0],
'DB_HOST').split(',')[1]
.split(')')[0].strip().replace('\'', ''))
# Check if database really exist
try:
if not WOMysql.check_db_exists(self, wo_db_name):
# Mark it as deleted if not exist
wo_db_name = 'deleted'
wo_db_user = 'deleted'
wo_db_pass = 'deleted'
except StatementExcecutionError as e:
Log.debug(self, str(e))
except Exception as e:
Log.debug(self, str(e))
if site.db_name != wo_db_name:
# update records if any mismatch found
Log.debug(self, "Updating wo db record for {0}"
.format(site.sitename))
updateSiteInfo(self, site.sitename,
db_name=wo_db_name,
db_user=wo_db_user,
db_password=wo_db_pass,
db_host=wo_db_host)
else:
Log.debug(self, "Config files not found for {0} "
.format(site.sitename))
def load(app):
# register the plugin class.. this only happens if the plugin is enabled
handler.register(WOSyncController)
# register a hook (function) to run after arguments are parsed.
hook.register('post_argument_parsing', wo_sync_hook)

44
wo/cli/plugins/update.py Normal file
View File

@@ -0,0 +1,44 @@
from cement.core.controller import CementBaseController, expose
from cement.core import handler, hook
from wo.core.download import WODownload
from wo.core.logging import Log
import time
import os
def wo_update_hook(app):
pass
class WOUpdateController(CementBaseController):
class Meta:
label = 'wo_update'
stacked_on = 'base'
aliases = ['update']
aliases_only = True
stacked_type = 'nested'
description = ('update WordOps to latest version')
usage = "wo update"
@expose(hide=True)
def default(self):
filename = "woupdate" + time.strftime("%Y%m%d-%H%M%S")
WODownload.download(self, [["https://wrdps.nl/woup",
"/tmp/{0}".format(filename),
"update script"]])
try:
Log.info(self, "updating WordOps, please wait...")
os.system("bash /tmp/{0}".format(filename))
except OSError as e:
Log.debug(self, str(e))
Log.error(self, "WordOps update failed !")
except Exception as e:
Log.debug(self, str(e))
Log.error(self, "WordOps update failed !")
def load(app):
# register the plugin class.. this only happens if the plugin is enabled
handler.register(WOUpdateController)
# register a hook (function) to run after arguments are parsed.
hook.register('post_argument_parsing', wo_update_hook)

View File

@@ -0,0 +1,27 @@
use strict;
# You can modify this file to re-enable SPAM checking through spamassassin
# and to re-enable antivirus checking.
#
# Default antivirus checking mode
# Please note, that anti-virus checking is DISABLED by
# default.
# If You wish to enable it, please uncomment the following lines:
@bypass_virus_checks_maps = (
\%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
#
# Default SPAM checking mode
# Please note, that anti-spam checking is DISABLED by
# default.
# If You wish to enable it, please uncomment the following lines:
@bypass_spam_checks_maps = (
\%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);
1; # ensure a defined return

View File

@@ -0,0 +1,44 @@
# WordOps admin NGINX CONFIGURATION
server {
listen 22222 default_server ssl http2;
access_log /var/log/nginx/22222.access.log rt_cache;
error_log /var/log/nginx/22222.error.log;
ssl_certificate {{webroot}}22222/cert/22222.crt;
ssl_certificate_key {{webroot}}22222/cert/22222.key;
# Force HTTP to HTTPS
error_page 497 =200 https://$host:22222$request_uri;
root {{webroot}}22222/htdocs;
index index.php index.htm index.html;
# Turn on directory listing
autoindex on;
# HTTP Authentication on port 22222
include common/acl.conf;
location / {
try_files $uri $uri/ /index.php?$args;
}
# Display menu at location /fpm/status/
location = /fpm/status/ {}
location ~ /fpm/status/(.*) {
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_NAME /status;
fastcgi_pass $1;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass php;
}
}

View File

View File

@@ -0,0 +1,8 @@
# WordOps (wo) protect locations using
# HTTP authentication || IP address
satisfy any;
auth_basic "Restricted Area";
auth_basic_user_file htpasswd-wo;
# Allowed IP Address List
allow 127.0.0.1;
deny all;

View File

@@ -0,0 +1,255 @@
<?php
$conf['datasources']['localhost'] = array(
'host' => '{{host}}',
'port' => '{{port}}',
'db' => 'slow_query_log',
'user' => '{{user}}',
'password' => '{{password}}',
'tables' => array(
'global_query_review' => 'fact',
'global_query_review_history' => 'dimension'
),
'source_type' => 'slow_query_log'
);
$conf['default_report_action'] = 'report';
$conf['reviewers'] = array( 'dba1','dba2');
$conf['review_types'] = array( 'good', 'bad', 'ticket-created', 'needs-fix', 'fixed', 'needs-analysis', 'review-again');
$conf['history_defaults'] = array(
'output' => 'table',
'fact-group' => 'date',
'fact-order' => 'date DESC',
'fact-limit' => '90',
'dimension-ts_min_start' => date("Y-m-d H:i:s", strtotime( '-90 day')),
'dimension-ts_min_end' => date("Y-m-d H:i:s"),
'table_fields' => array('date', 'index_ratio','query_time_avg','rows_sent_avg','ts_cnt','Query_time_sum','Lock_time_sum','Rows_sent_sum','Rows_examined_sum','Tmp_table_sum','Filesort_sum','Full_scan_sum')
);
$conf['report_defaults'] = array(
'fact-group' => 'checksum',
'fact-order' => 'Query_time_sum DESC',
'fact-limit' => '20',
'dimension-ts_min_start' => date("Y-m-d H:i:s", strtotime( '-1 day')),
'dimension-ts_min_end' => date("Y-m-d H:i:s"),
'table_fields' => array('checksum','snippet', 'index_ratio','query_time_avg','rows_sent_avg','ts_cnt','Query_time_sum','Lock_time_sum','Rows_sent_sum','Rows_examined_sum','Tmp_table_sum','Filesort_sum','Full_scan_sum'),
'dimension-pivot-hostname_max' => null
);
$conf['graph_defaults'] = array(
'fact-group' => 'minute_ts',
'fact-order' => 'minute_ts',
'fact-limit' => '',
'dimension-ts_min_start' => date("Y-m-d H:i:s", strtotime( '-7 day')),
'dimension-ts_min_end' => date("Y-m-d H:i:s"),
'table_fields' => array('minute_ts'),
'plot_field' => 'Query_time_sum',
);
$conf['report_defaults']['performance_schema'] = array(
'fact-order' => 'SUM_TIMER_WAIT DESC',
'fact-limit' => '20',
'fact-group' => 'DIGEST',
'table_fields' => array( 'DIGEST', 'snippet', 'index_ratio', 'COUNT_STAR', 'SUM_TIMER_WAIT', 'SUM_LOCK_TIME','SUM_ROWS_AFFECTED','SUM_ROWS_SENT','SUM_ROWS_EXAMINED','SUM_CREATED_TMP_TABLES','SUM_SORT_SCAN','SUM_NO_INDEX_USED' )
);
$conf['history_defaults']['performance_schema'] = array(
'fact-order' => 'SUM_TIMER_WAIT DESC',
'fact-limit' => '20',
'fact-group' => 'DIGEST',
'table_fields' => array( 'DIGEST', 'index_ratio', 'COUNT_STAR', 'SUM_LOCK_TIME','SUM_ROWS_AFFECTED','SUM_ROWS_SENT','SUM_ROWS_EXAMINED','SUM_CREATED_TMP_TABLES','SUM_SORT_SCAN','SUM_NO_INDEX_USED' )
);
$conf['report_defaults']['performance_schema_history'] = array(
'fact-group' => 'DIGEST',
'fact-order' => 'SUM_TIMER_WAIT DESC',
'fact-limit' => '20',
'dimension-FIRST_SEEN_start' => date("Y-m-d H:i:s", strtotime( '-1 day')),
'dimension-FIRST_SEEN_end' => date("Y-m-d H:i:s"),
'table_fields' => array( 'DIGEST', 'snippet', 'index_ratio', 'COUNT_STAR', 'SUM_LOCK_TIME','SUM_ROWS_AFFECTED','SUM_ROWS_SENT','SUM_ROWS_EXAMINED','SUM_CREATED_TMP_TABLES','SUM_SORT_SCAN','SUM_NO_INDEX_USED' )
);
$conf['graph_defaults']['performance_schema_history'] = array(
'fact-group' => 'minute_ts',
'fact-order' => 'minute_ts',
'fact-limit' => '',
'dimension-FIRST_SEEN_start' => date("Y-m-d H:i:s", strtotime( '-7 day')),
'dimension-FIRST_SEEN_end' => date("Y-m-d H:i:s"),
'table_fields' => array('minute_ts'),
'plot_field' => 'SUM_TIMER_WAIT',
'dimension-pivot-hostname_max' => null
);
$conf['history_defaults']['performance_schema_history'] = array(
'output' => 'table',
'fact-group' => 'date',
'fact-order' => 'date DESC',
'fact-limit' => '90',
'dimension-FIRST_SEEN_start' => date("Y-m-d H:i:s", strtotime( '-90 day')),
'dimension-FIRST_SEEN_end' => date("Y-m-d H:i:s"),
'table_fields' => array( 'date', 'snippet', 'index_ratio', 'COUNT_STAR', 'SUM_LOCK_TIME','SUM_ROWS_AFFECTED','SUM_ROWS_SENT','SUM_ROWS_EXAMINED','SUM_CREATED_TMP_TABLES','SUM_SORT_SCAN','SUM_NO_INDEX_USED' )
);
$conf['plugins'] = array(
'visual_explain' => '/usr/bin/pt-visual-explain',
'query_advisor' => '/usr/bin/pt-query-advisor',
'show_create' => true,
'show_status' => true,
'explain' => function ($sample) {
$conn = array();
if (!array_key_exists('hostname_max',$sample) or strlen($sample['hostname_max']) < 5)
{
return;
}
$pos = strpos($sample['hostname_max'], ':');
if ($pos === false)
{
$conn['port'] = 3306;
$conn['host'] = $sample['hostname_max'];
}
else
{
$parts = preg_split("/:/", $sample['hostname_max']);
$conn['host'] = $parts[0];
$conn['port'] = $parts[1];
}
$conn['db'] = 'mysql';
if ($sample['db_max'] != '')
{
$conn['db'] = $sample['db_max'];
}
$conn['user'] = '{{user}}';
$conn['password'] = '{{password}}';
return $conn;
},
);
$conf['reports']['slow_query_log'] = array(
'join' => array (
'dimension' => 'USING (`checksum`)'
),
'fields' => array(
'fact' => array(
'group' => 'group',
'order' => 'order',
'having' => 'having',
'limit' => 'limit',
'first_seen'=> 'clear|reldate|ge|where',
'where' => 'raw_where',
'sample' => 'clear|like|where',
'checksum' => 'clear|where',
'reviewed_status' => 'clear|where',
),
'dimension' => array(
'extra_fields' => 'where',
'hostname_max' => 'clear|where',
'ts_min' => 'date_range|reldate|clear|where',
'pivot-hostname_max' => 'clear|pivot|select',
'pivot-checksum' => 'clear|pivot|select',
),
),
'custom_fields' => array(
'checksum' => 'checksum',
'date' => 'DATE(ts_min)',
'hour' => 'substring(ts_min,1,13)',
'hour_ts' => 'round(unix_timestamp(substring(ts_min,1,13)))',
'minute_ts' => 'round(unix_timestamp(substring(ts_min,1,16)))',
'minute' => 'substring(ts_min,1,16)',
'snippet' => 'LEFT(dimension.sample,20)',
'index_ratio' =>'ROUND(SUM(Rows_examined_sum)/SUM(rows_sent_sum),2)',
'query_time_avg' => 'SUM(Query_time_sum) / SUM(ts_cnt)',
'rows_sent_avg' => 'ROUND(SUM(Rows_sent_sum)/SUM(ts_cnt),0)',
),
'callbacks' => array(
'table' => array(
'date' => function ($x) { $type=''; if ( date('N',strtotime($x)) >= 6) { $type = 'weekend'; } return array($x,$type); },
'checksum' => function ($x) { return array(dec2hex($x), ''); }
)
)
);
$conf['reports']['performance_schema'] = array(
'fields' => array(
'fact' => array(
'order' => 'order',
'having' => 'having',
'limit' => 'limit',
'first_seen' => 'date_range|reldate|clear|where',
'where' => 'raw_where',
'DIGEST' => 'clear|where',
'DIGEST_TEXT' => 'clear|like|where',
'group' => 'group',
),
),
'custom_fields' => array(
'snippet' => 'LEFT(fact.DIGEST_TEXT,20)',
'index_ratio' =>'ROUND(SUM_ROWS_EXAMINED/SUM_ROWS_SENT,2)',
'rows_sent_avg' => 'ROUND(SUM_ROWS_SENT/COUNT_STAR,0)',
),
'special_field_names' => array(
'time' => 'FIRST_SEEN',
'checksum' => 'DIGEST',
'sample' => 'DIGEST_TEXT',
'fingerprint' => 'DIGEST_TEXT',
),
);
$conf['reports']['performance_schema_history'] = array(
'join' => array (
'dimension' => 'USING (`DIGEST`)'
),
'fields' => array(
'fact' => array(
'group' => 'group',
'order' => 'order',
'having' => 'having',
'limit' => 'limit',
'first_seen'=> 'clear|reldate|ge|where',
'where' => 'raw_where',
'DIGEST_TEXT' => 'clear|like|where',
'DIGEST' => 'clear|where',
'reviewed_status' => 'clear|where',
),
'dimension' => array(
'extra_fields' => 'where',
'hostname' => 'clear|where',
'FIRST_SEEN' => 'date_range|reldate|clear|where',
'pivot-hostname' => 'clear|pivot|select',
),
),
'custom_fields' => array(
'date' => 'DATE(fact.FIRST_SEEN)',
'snippet' => 'LEFT(fact.DIGEST_TEXT,20)',
'index_ratio' =>'ROUND(SUM_ROWS_EXAMINED/SUM_ROWS_SENT,2)',
'rows_sent_avg' => 'ROUND(SUM_ROWS_SENT/COUNT_STAR,0)',
'hour' => 'substring(dimension.FIRST_SEEN,1,13)',
'hour_ts' => 'round(unix_timestamp(substring(dimension.FIRST_SEEN,1,13)))',
'minute_ts' => 'round(unix_timestamp(substring(dimension.FIRST_SEEN,1,16)))',
'minute' => 'substring(dimension.FIRST_SEEN,1,16)',
),
'special_field_names' => array(
'time' => 'FIRST_SEEN',
'checksum' => 'DIGEST',
'hostname' => 'hostname',
'sample' => 'DIGEST_TEXT'
),
);
?>

View File

@@ -0,0 +1,2 @@
# Block IP Address
# deny 1.1.1.1;

View File

@@ -0,0 +1,10 @@
# FastCGI cache settings
fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:50m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_503;
fastcgi_cache_valid 200 301 302 404 1h;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_param SERVER_NAME $http_host;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
fastcgi_keep_conn on;

View File

@@ -0,0 +1,10 @@
MySQL ({{version}}) on {{host}}:
port {{port}}
wait_timeout {{wait_timeout}}
interactive_timeout {{interactive_timeout}}
max_used_connections {{max_used_connections}}
datadir {{datadir}}
socket {{socket}}
my.cnf [PATH] /etc/mysql/conf.d/my.cnf

View File

@@ -0,0 +1,10 @@
NGINX ({{version}}):
user {{user}}
worker_processes {{worker_processes}}
worker_connections {{worker_connections}}
keepalive_timeout {{keepalive_timeout}}
fastcgi_read_timeout {{fastcgi_read_timeout}}
client_max_body_size {{client_max_body_size}}
allow {{allow}}

View File

@@ -0,0 +1,35 @@
PHP ({{version}}):
user {{user}}
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}}
Information about www.conf
ping.path {{www_ping_path}}
pm.status_path {{www_pm_status_path}}
process_manager {{www_pm}}
pm.max_requests {{www_pm_max_requests}}
pm.max_children {{www_pm_max_children}}
pm.start_servers {{www_pm_start_servers}}
pm.min_spare_servers {{www_pm_min_spare_servers}}
pm.max_spare_servers {{www_pm_max_spare_servers}}
request_terminate_timeout {{www_request_terminate_timeout}}
xdebug.profiler_enable_trigger {{www_xdebug_profiler_enable_trigger}}
listen {{www_listen}}
Information about debug.conf
ping.path {{debug_ping_path}}
pm.status_path {{debug_pm_status_path}}
process_manager {{debug_pm}}
pm.max_requests {{debug_pm_max_requests}}
pm.max_children {{debug_pm_max_children}}
pm.start_servers {{debug_pm_start_servers}}
pm.min_spare_servers {{debug_pm_min_spare_servers}}
pm.max_spare_servers {{debug_pm_max_spare_servers}}
request_terminate_timeout {{debug_request_terminate_timeout}}
xdebug.profiler_enable_trigger {{debug_xdebug_profiler_enable_trigger}}
listen {{debug_listen}}

View File

@@ -0,0 +1,68 @@
# NGINX CONFIGURATION FOR COMMON LOCATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
# Basic locations files
location = /favicon.ico {
access_log off;
log_not_found off;
expires max;
}
location = /robots.txt {
# Some WordPress plugin gererate robots.txt file
# Refer #340 issue
try_files $uri $uri/ /index.php?$args;
access_log off;
log_not_found off;
}
# Cache static files
location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|swf)$ {
add_header "Access-Control-Allow-Origin" "*";
access_log off;
log_not_found off;
expires max;
}
# Security settings for better privacy
# Deny hidden files
location ~ /\.well-known {
allow all;
}
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Deny backup extensions & log files
location ~* ^.+\.(bak|log|old|orig|original|php#|php~|php_bak|save|swo|swp|sql)$ {
deny all;
access_log off;
log_not_found off;
}
# Return 403 forbidden for readme.(txt|html) or license.(txt|html) or example.(txt|html)
if ($uri ~* "^.+(readme|license|example)\.(txt|html)$") {
return 403;
}
# Status pages
location = /nginx_status {
stub_status on;
access_log off;
include common/acl.conf;
}
location ~ ^/(status|ping)$ {
include fastcgi_params;
fastcgi_pass php7;
include common/acl.conf;
}
# WordOps (wo) utilities
# phpMyAdmin settings
location = /pma {
return 301 https://$host:22222/db/pma;
}
location = /phpMyAdmin {
return 301 https://$host:22222/db/pma;
}
location = /phpmyadmin {
return 301 https://$host:22222/db/pma;
}
# Adminer settings
location = /adminer {
return 301 https://$host:22222/db/adminer;
}

View File

@@ -0,0 +1,68 @@
# NGINX CONFIGURATION FOR COMMON LOCATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
# Basic locations files
location = /favicon.ico {
access_log off;
log_not_found off;
expires max;
}
location = /robots.txt {
# Some WordPress plugin gererate robots.txt file
# Refer #340 issue
try_files $uri $uri/ /index.php?$args;
access_log off;
log_not_found off;
}
# Cache static files
location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|swf)$ {
add_header "Access-Control-Allow-Origin" "*";
access_log off;
log_not_found off;
expires max;
}
# Security settings for better privacy
# Deny hidden files
location ~ /\.well-known {
allow all;
}
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Deny backup extensions & log files
location ~* ^.+\.(bak|log|old|orig|original|php#|php~|php_bak|save|swo|swp|sql)$ {
deny all;
access_log off;
log_not_found off;
}
# Return 403 forbidden for readme.(txt|html) or license.(txt|html) or example.(txt|html)
if ($uri ~* "^.+(readme|license|example)\.(txt|html)$") {
return 403;
}
# Status pages
location = /nginx_status {
stub_status on;
access_log off;
include common/acl.conf;
}
location ~ ^/(status|ping)$ {
include fastcgi_params;
fastcgi_pass php;
include common/acl.conf;
}
# WordOps (wo) utilities
# phpMyAdmin settings
location = /pma {
return 301 https://$host:22222/db/pma;
}
location = /phpMyAdmin {
return 301 https://$host:22222/db/pma;
}
location = /phpmyadmin {
return 301 https://$host:22222/db/pma;
}
# Adminer settings
location = /adminer {
return 301 https://$host:22222/db/adminer;
}

View File

@@ -0,0 +1,60 @@
##
# WordOps Settings
##
server_tokens off;
reset_timedout_connection on;
add_header X-Powered-By "WordOps {{version}}";
# Limit Request
limit_req_status 403;
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
# Proxy Settings
# set_real_ip_from proxy-server-ip;
# real_ip_header X-Forwarded-For;
fastcgi_read_timeout 300;
client_max_body_size 100m;
# SSL Settings
ssl_protocols TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
{{#Ubuntu}}
ssl_prefer_server_ciphers on;
{{/Ubuntu}}
ssl_ciphers "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
# Log format Settings
log_format rt_cache '$remote_addr $upstream_response_time $upstream_cache_status [$time_local] '
'$http_host "$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
# GZip settings
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
# Compress all output labeled with one of the following MIME-types.
gzip_types
application/atom+xml
application/javascript
application/json
application/rss+xml
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/svg+xml
image/x-icon
text/css
text/plain
text/x-component
text/xml
text/javascript;
# text/html is always compressed by HttpGzipModule

View File

@@ -0,0 +1,5 @@
[global]
pid = {{pid}}
error_log = {{error_log}}
log_level = notice
include = {{include}}

View File

@@ -0,0 +1,10 @@
# PHP NGINX CONFIGURATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass hhvm;
}

View File

@@ -0,0 +1,10 @@
# PHP NGINX CONFIGURATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass php;
}

View File

@@ -0,0 +1,10 @@
# PHP NGINX CONFIGURATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass php7;
}

View File

@@ -0,0 +1,58 @@
# Redis NGINX CONFIGURATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
set $skip_cache 0;
# POST requests and URL with a query string should always go to php
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
# Don't cache URL containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|wp-.*\.php|index.php|/feed/|.*sitemap.*\.xml)") {
set $skip_cache 1;
}
# Don't use the cache for logged in users or recent commenter or customer with items in cart
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|[a-z0-9]+_items_in_cart") {
set $skip_cache 1;
}
# Use cached or actual file if they exists, Otherwise pass request to WordPress
location / {
try_files $uri $uri/ /index.php?$args;
}
location /redis-fetch {
internal ;
set $redis_key $args;
redis_pass redis;
}
location /redis-store {
internal ;
set_unescape_uri $key $arg_key ;
redis2_query set $key $echo_request_body;
redis2_query expire $key 14400;
redis2_pass redis;
}
location ~ \.php$ {
set $key "nginx-cache:$scheme$request_method$host$request_uri";
try_files $uri =404;
srcache_fetch_skip $skip_cache;
srcache_store_skip $skip_cache;
srcache_response_cache_control off;
set_escape_uri $escaped_key $key;
srcache_fetch GET /redis-fetch $key;
srcache_store PUT /redis-store key=$escaped_key;
more_set_headers 'X-SRCache-Fetch-Status $srcache_fetch_status';
more_set_headers 'X-SRCache-Store-Status $srcache_store_status';
include fastcgi_params;
fastcgi_param HTTP_ACCEPT_ENCODING "";
fastcgi_pass hhvm;
}

View File

@@ -0,0 +1,56 @@
# Redis NGINX CONFIGURATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
set $skip_cache 0;
# POST requests and URL with a query string should always go to php
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
# Don't cache URL containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|wp-.*\.php|index.php|/feed/|.*sitemap.*\.xml)") {
set $skip_cache 1;
}
# Don't use the cache for logged in users or recent commenter or customer with items in cart
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|[a-z0-9]+_items_in_cart") {
set $skip_cache 1;
}
# Use cached or actual file if they exists, Otherwise pass request to WordPress
location / {
try_files $uri $uri/ /index.php?$args;
}
location /redis-fetch {
internal ;
set $redis_key $args;
redis_pass redis;
}
location /redis-store {
internal ;
set_unescape_uri $key $arg_key ;
redis2_query set $key $echo_request_body;
redis2_query expire $key 14400;
redis2_pass redis;
}
location ~ \.php$ {
set $key "nginx-cache:$scheme$request_method$host$request_uri";
try_files $uri =404;
srcache_fetch_skip $skip_cache;
srcache_store_skip $skip_cache;
srcache_response_cache_control off;
set_escape_uri $escaped_key $key;
srcache_fetch GET /redis-fetch $key;
srcache_store PUT /redis-store key=$escaped_key;
more_set_headers 'X-SRCache-Fetch-Status $srcache_fetch_status';
more_set_headers 'X-SRCache-Store-Status $srcache_store_status';
include fastcgi_params;
fastcgi_pass php7;
}

View File

@@ -0,0 +1,57 @@
# Redis NGINX CONFIGURATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
set $skip_cache 0;
# POST requests and URL with a query string should always go to php
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
# Don't cache URL containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|wp-.*\.php|index.php|/feed/|.*sitemap.*\.xml)") {
set $skip_cache 1;
}
# Don't use the cache for logged in users or recent commenter or customer with items in cart
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|[a-z0-9]+_items_in_cart") {
set $skip_cache 1;
}
# Use cached or actual file if they exists, Otherwise pass request to WordPress
location / {
try_files $uri $uri/ /index.php?$args;
}
location /redis-fetch {
internal ;
set $redis_key $args;
redis_pass redis;
}
location /redis-store {
internal ;
set_unescape_uri $key $arg_key ;
redis2_query set $key $echo_request_body;
redis2_query expire $key 14400;
redis2_pass redis;
}
location ~ \.php$ {
set $key "nginx-cache:$scheme$request_method$host$request_uri";
try_files $uri =404;
srcache_fetch_skip $skip_cache;
srcache_store_skip $skip_cache;
srcache_response_cache_control off;
set_escape_uri $escaped_key $key;
srcache_fetch GET /redis-fetch $key;
srcache_store PUT /redis-store key=$escaped_key;
more_set_headers 'X-SRCache-Fetch-Status $srcache_fetch_status';
more_set_headers 'X-SRCache-Store-Status $srcache_store_status';
include fastcgi_params;
fastcgi_pass php;
}

View File

@@ -0,0 +1,15 @@
Information about {{domain}}:
Nginx configuration {{type}} {{enable}}
{{#php_version}}PHP Version {{php_version}}{{/php_version}}
{{#hhvm}}HHVM {{hhvm}}{{/hhvm}}
{{#ssl}}SSL {{ssl}}{{/ssl}}
{{#sslprovider}}SSL PROVIDER {{sslprovider}}{{/sslprovider}}
{{#sslexpiry}}SSL EXPIRY DATE {{sslexpiry}}{{/sslexpiry}}
access_log {{accesslog}}
error_log {{errorlog}}
{{#webroot}}Webroot {{webroot}}{{/webroot}}
{{#dbname}}DB_NAME {{dbname}}{{/dbname}}
{{#dbname}}DB_USER {{dbuser}}{{/dbname}}
{{#dbname}}DB_PASS {{dbpass}}{{/dbname}}
{{#tablepref}}table_prefix {{tableprefix}}{{/tablepref}}

View File

@@ -0,0 +1,26 @@
# Common upstream settings
upstream php {
# server unix:/run/php5-fpm.sock;
server 127.0.0.1:{{php}};
}
upstream debug {
# Debug Pool
server 127.0.0.1:{{debug}};
}
{{#php7conf}}
upstream php7 {
server 127.0.0.1:{{php7}};
}
upstream debug7 {
# Debug Pool
server 127.0.0.1:{{debug7}};
}
{{/php7conf}}
{{#hhvmconf}}
upstream hhvm {
# HHVM Pool
server 127.0.0.1:{{hhvm}};
server 127.0.0.1:{{php}} backup;
}
{{/hhvmconf}}

View File

@@ -0,0 +1,47 @@
server {
{{#multisite}}
# Uncomment the following line for domain mapping
# listen 80 default_server;
{{/multisite}}
server_name {{^vma}}{{^rc}}{{site_name}}{{/rc}}{{/vma}} {{#vma}}vma.*{{/vma}} {{#rc}}webmail.*{{/rc}} {{^vma}}{{^rc}}{{#multisite}}*{{/multisite}}{{^multisite}}www{{/multisite}}.{{site_name}}{{/rc}}{{/vma}};
{{#multisite}}
# Uncomment the following line for domain mapping
#server_name_in_redirect off;
{{/multisite}}
access_log /var/log/nginx/{{site_name}}.access.log {{^wpredis}}{{^static}}rt_cache{{/static}}{{/wpredis}}{{#wpredis}}rt_cache_redis{{/wpredis}};
error_log /var/log/nginx/{{site_name}}.error.log;
{{#proxy}}
add_header X-Proxy-Cache $upstream_cache_status;
location / {
proxy_pass http://{{host}}:{{port}};
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
{{/proxy}}
{{^proxy}}
{{^vma}}{{^rc}}root {{webroot}}/htdocs;{{/rc}}{{/vma}}
{{^proxy}}index {{^static}}index.php{{/static}} index.html index.htm;{{/proxy}}
{{#static}}
location / {
try_files $uri $uri/ =404;
}
{{/static}}
{{^static}}include {{^hhvm}}{{#basic}}common/php7.conf;{{/basic}}{{#wpfc}}common/wpfc-php7.conf;{{/wpfc}} {{#wpsc}}common/wpsc-php7.conf;{{/wpsc}}{{#wpredis}}common/redis-php7.conf;{{/wpredis}} {{/hhvm}}{{#hhvm}}{{#basic}}common/php-hhvm.conf;{{/basic}}{{#wpfc}}common/wpfc-hhvm.conf;{{/wpfc}} {{#wpsc}}common/wpsc-hhvm.conf;{{/wpsc}}{{#wpredis}}common/redis-hhvm.conf;{{/wpredis}} {{/hhvm}}
{{#wpsubdir}}include common/wpsubdir.conf;{{/wpsubdir}}{{/static}}
{{#wp}}include common/wpcommon-php7.conf;{{/wp}}
{{^proxy}}include common/locations-php7.conf;{{/proxy}}
{{^vma}}{{^rc}}include {{webroot}}/conf/nginx/*.conf;{{/rc}}{{/vma}}
{{/proxy}}
}

View File

@@ -0,0 +1,46 @@
server {
{{#multisite}}
# Uncomment the following line for domain mapping
# listen 80 default_server;
{{/multisite}}
server_name {{^vma}}{{^rc}}{{site_name}}{{/rc}}{{/vma}} {{#vma}}vma.*{{/vma}} {{#rc}}webmail.*{{/rc}} {{^vma}}{{^rc}}{{#multisite}}*{{/multisite}}{{^multisite}}www{{/multisite}}.{{site_name}}{{/rc}}{{/vma}};
{{#multisite}}
# Uncomment the following line for domain mapping
#server_name_in_redirect off;
{{/multisite}}
access_log /var/log/nginx/{{site_name}}.access.log {{^wpredis}}{{^static}}rt_cache{{/static}}{{/wpredis}}{{#wpredis}}rt_cache_redis{{/wpredis}};
error_log /var/log/nginx/{{site_name}}.error.log;
{{#proxy}}
add_header X-Proxy-Cache $upstream_cache_status;
location / {
proxy_pass http://{{host}}:{{port}};
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
{{/proxy}}
{{^proxy}}
{{^vma}}{{^rc}}root {{webroot}}/htdocs;{{/rc}}{{/vma}}
{{^proxy}}index {{^static}}index.php{{/static}} index.html index.htm;{{/proxy}}
{{#static}}
location / {
try_files $uri $uri/ =404;
}
{{/static}}
{{^static}}include {{^hhvm}}{{#basic}}common/php.conf;{{/basic}}{{#wpfc}}common/wpfc.conf;{{/wpfc}} {{#wpsc}}common/wpsc.conf;{{/wpsc}}{{#wpredis}}common/redis.conf;{{/wpredis}} {{/hhvm}}{{#hhvm}}{{#basic}}common/php-hhvm.conf;{{/basic}}{{#wpfc}}common/wpfc-hhvm.conf;{{/wpfc}} {{#wpsc}}common/wpsc-hhvm.conf;{{/wpsc}}{{#wpredis}}common/redis-hhvm.conf;{{/wpredis}} {{/hhvm}} {{#wpsubdir}}include common/wpsubdir.conf;{{/wpsubdir}}{{/static}}
{{#wp}}include common/wpcommon.conf;{{/wp}}
{{^proxy}}include common/locations.conf;{{/proxy}}
{{^vma}}{{^rc}}include {{webroot}}/conf/nginx/*.conf;{{/rc}}{{/vma}}
{{/proxy}}
}

View File

@@ -0,0 +1,83 @@
##
# WordOps Settings
##
tcp_nopush on;
tcp_nodelay on;
types_hash_max_size 2048;
server_tokens off;
reset_timedout_connection on;
add_header X-Powered-By "WordOps {{ version }}";
# Limit Request
limit_req_status 403;
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
# Proxy Settings
# set_real_ip_from proxy-server-ip;
# real_ip_header X-Forwarded-For;
fastcgi_read_timeout 300;
client_max_body_size 100m;
##
# SSL Settings
##
ssl_session_cache shared:SSL:5m;
ssl_session_timeout 10m;
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_protocols TLSv1.1 TLSv1.2;
##
# Basic Settings
##
server_names_hash_bucket_size 16384;
# server_name_in_redirect off;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Log format Settings
log_format rt_cache '$remote_addr $upstream_response_time $upstream_cache_status [$time_local] '
'$http_host "$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$request_body"';
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types
application/atom+xml
application/javascript
application/json
application/rss+xml
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/svg+xml
image/x-icon
text/css
text/plain
text/x-component
text/xml
text/javascript;

View File

@@ -0,0 +1,21 @@
# WordPress COMMON SETTINGS
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
# Limit access to avoid brute force attack
location = /wp-login.php {
limit_req zone=one burst=1 nodelay;
include fastcgi_params;
fastcgi_pass php7;
}
# Disable wp-config.txt
location = /wp-config.txt {
deny all;
access_log off;
log_not_found off;
}
# Disallow php in upload folder
location /wp-content/uploads/ {
location ~ \.php$ {
#Prevent Direct Access Of PHP Files From Web Browsers
deny all;
}
}

View File

@@ -0,0 +1,21 @@
# WordPress COMMON SETTINGS
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
# Limit access to avoid brute force attack
location = /wp-login.php {
limit_req zone=one burst=1 nodelay;
include fastcgi_params;
fastcgi_pass php;
}
# Disable wp-config.txt
location = /wp-config.txt {
deny all;
access_log off;
log_not_found off;
}
# Disallow php in upload folder
location /wp-content/uploads/ {
location ~ \.php$ {
#Prevent Direct Access Of PHP Files From Web Browsers
deny all;
}
}

View File

@@ -0,0 +1,37 @@
# WPFC NGINX CONFIGURATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
set $skip_cache 0;
# POST requests and URL with a query string should always go to php
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
# Don't cache URL containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|wp-.*\.php|index.php|/feed/|.*sitemap.*\.xml)") {
set $skip_cache 1;
}
# Don't use the cache for logged in users or recent commenter or customer with items in cart
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|[a-z0-9]+_items_in_cart") {
set $skip_cache 1;
}
# Use cached or actual file if they exists, Otherwise pass request to WordPress
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ ^/wp-content/cache/minify/(.+\.(css|js))$ {
try_files $uri /wp-content/plugins/w3-total-cache/pub/minify.php?file=$1;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass hhvm;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache WORDPRESS;
}
location ~ /purge(/.*) {
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
access_log off;
}

View File

@@ -0,0 +1,37 @@
# WPFC NGINX CONFIGURATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
set $skip_cache 0;
# POST requests and URL with a query string should always go to php
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
# Don't cache URL containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|wp-.*\.php|index.php|/feed/|.*sitemap.*\.xml)") {
set $skip_cache 1;
}
# Don't use the cache for logged in users or recent commenter or customer with items in cart
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|[a-z0-9]+_items_in_cart") {
set $skip_cache 1;
}
# Use cached or actual file if they exists, Otherwise pass request to WordPress
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ ^/wp-content/cache/minify/(.+\.(css|js))$ {
try_files $uri /wp-content/plugins/w3-total-cache/pub/minify.php?file=$1;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass php7;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache WORDPRESS;
}
location ~ /purge(/.*) {
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
access_log off;
}

View File

@@ -0,0 +1,37 @@
# WPFC NGINX CONFIGURATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
set $skip_cache 0;
# POST requests and URL with a query string should always go to php
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
# Don't cache URL containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|wp-.*\.php|index.php|/feed/|.*sitemap.*\.xml)") {
set $skip_cache 1;
}
# Don't use the cache for logged in users or recent commenter or customer with items in cart
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|[a-z0-9]+_items_in_cart") {
set $skip_cache 1;
}
# Use cached or actual file if they exists, Otherwise pass request to WordPress
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ ^/wp-content/cache/minify/(.+\.(css|js))$ {
try_files $uri /wp-content/plugins/w3-total-cache/pub/minify.php?file=$1;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass php;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache WORDPRESS;
}
location ~ /purge(/.*) {
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
access_log off;
}

View File

@@ -0,0 +1,31 @@
# WPSC NGINX CONFIGURATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
set $cache_uri $request_uri;
# POST requests and URL with a query string should always go to php
if ($request_method = POST) {
set $cache_uri 'null cache';
}
if ($query_string != "") {
set $cache_uri 'null cache';
}
# Don't cache URL containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|wp-.*\.php|index.php|/feed/|.*sitemap.*\.xml)") {
set $cache_uri 'null cache';
}
# Don't use the cache for logged in users or recent commenter or customer with items in cart
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|[a-z0-9]+_items_in_cart") {
set $cache_uri 'null cache';
}
# Use cached or actual file if they exists, Otherwise pass request to WordPress
location / {
# If we add index.php?$args its break WooCommerce like plugins
# Ref: #330
try_files /wp-content/cache/supercache/$http_host/$cache_uri/index.html $uri $uri/ /index.php;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass hhvm;
# Following line is needed by WP Super Cache plugin
fastcgi_param SERVER_NAME $http_host;
}

View File

@@ -0,0 +1,31 @@
# WPSC NGINX CONFIGURATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
set $cache_uri $request_uri;
# POST requests and URL with a query string should always go to php
if ($request_method = POST) {
set $cache_uri 'null cache';
}
if ($query_string != "") {
set $cache_uri 'null cache';
}
# Don't cache URL containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|wp-.*\.php|index.php|/feed/|.*sitemap.*\.xml)") {
set $cache_uri 'null cache';
}
# Don't use the cache for logged in users or recent commenter or customer with items in cart
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|[a-z0-9]+_items_in_cart") {
set $cache_uri 'null cache';
}
# Use cached or actual file if they exists, Otherwise pass request to WordPress
location / {
# If we add index.php?$args its break WooCommerce like plugins
# Ref: #330
try_files /wp-content/cache/supercache/$http_host/$cache_uri/index.html $uri $uri/ /index.php;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass php7;
# Following line is needed by WP Super Cache plugin
fastcgi_param SERVER_NAME $http_host;
}

View File

@@ -0,0 +1,31 @@
# WPSC NGINX CONFIGURATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
set $cache_uri $request_uri;
# POST requests and URL with a query string should always go to php
if ($request_method = POST) {
set $cache_uri 'null cache';
}
if ($query_string != "") {
set $cache_uri 'null cache';
}
# Don't cache URL containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|wp-.*\.php|index.php|/feed/|.*sitemap.*\.xml)") {
set $cache_uri 'null cache';
}
# Don't use the cache for logged in users or recent commenter or customer with items in cart
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|[a-z0-9]+_items_in_cart") {
set $cache_uri 'null cache';
}
# Use cached or actual file if they exists, Otherwise pass request to WordPress
location / {
# If we add index.php?$args its break WooCommerce like plugins
# Ref: #330
try_files /wp-content/cache/supercache/$http_host/$cache_uri/index.html $uri $uri/ /index.php;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass php;
# Following line is needed by WP Super Cache plugin
fastcgi_param SERVER_NAME $http_host;
}

View File

@@ -0,0 +1,10 @@
# WPSUBDIRECTORY NGINX CONFIGURATION
# DO NOT MODIFY, ALL CHANGES WILL BE LOST AFTER AN WordOps (wo) UPDATE
if (!-e $request_filename) {
# Redirect wp-admin to wp-admin/
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
# Redirect wp-* files/folders
rewrite ^(/[^/]+)?(/wp-.*) $2 last;
# Redirect other php files
rewrite ^(/[^/]+)?(/.*\.php) $2 last;
}