Refactored
This commit is contained in:
1
wo/__init__.py
Normal file
1
wo/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
__import__('pkg_resources').declare_namespace(__name__)
|
||||
0
wo/cli/__init__.py
Normal file
0
wo/cli/__init__.py
Normal file
11
wo/cli/bootstrap.py
Normal file
11
wo/cli/bootstrap.py
Normal 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)
|
||||
0
wo/cli/controllers/__init__.py
Normal file
0
wo/cli/controllers/__init__.py
Normal file
25
wo/cli/controllers/base.py
Normal file
25
wo/cli/controllers/base.py
Normal 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
0
wo/cli/ext/__init__.py
Normal file
20
wo/cli/ext/wo_outputhandler.py
Normal file
20
wo/cli/ext/wo_outputhandler.py
Normal 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
135
wo/cli/main.py
Normal 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()
|
||||
0
wo/cli/plugins/__init__.py
Normal file
0
wo/cli/plugins/__init__.py
Normal file
104
wo/cli/plugins/clean.py
Normal file
104
wo/cli/plugins/clean.py
Normal 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
856
wo/cli/plugins/debug.py
Normal 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)
|
||||
34
wo/cli/plugins/import_slow_log.py
Normal file
34
wo/cli/plugins/import_slow_log.py
Normal 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
289
wo/cli/plugins/info.py
Normal 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
577
wo/cli/plugins/log.py
Normal 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
57
wo/cli/plugins/models.py
Normal 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
141
wo/cli/plugins/secure.py
Normal 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
1735
wo/cli/plugins/site.py
Normal file
File diff suppressed because it is too large
Load Diff
1439
wo/cli/plugins/site_functions.py
Normal file
1439
wo/cli/plugins/site_functions.py
Normal file
File diff suppressed because it is too large
Load Diff
126
wo/cli/plugins/sitedb.py
Normal file
126
wo/cli/plugins/sitedb.py
Normal 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
2047
wo/cli/plugins/stack.py
Normal file
File diff suppressed because it is too large
Load Diff
115
wo/cli/plugins/stack_migrate.py
Normal file
115
wo/cli/plugins/stack_migrate.py
Normal 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")
|
||||
403
wo/cli/plugins/stack_services.py
Normal file
403
wo/cli/plugins/stack_services.py
Normal 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)
|
||||
233
wo/cli/plugins/stack_upgrade.py
Normal file
233
wo/cli/plugins/stack_upgrade.py
Normal 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
94
wo/cli/plugins/sync.py
Normal 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
44
wo/cli/plugins/update.py
Normal 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)
|
||||
27
wo/cli/templates/15-content_filter_mode.mustache
Normal file
27
wo/cli/templates/15-content_filter_mode.mustache
Normal 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
|
||||
44
wo/cli/templates/22222.mustache
Normal file
44
wo/cli/templates/22222.mustache
Normal 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;
|
||||
}
|
||||
}
|
||||
0
wo/cli/templates/__init__.py
Normal file
0
wo/cli/templates/__init__.py
Normal file
8
wo/cli/templates/acl.mustache
Normal file
8
wo/cli/templates/acl.mustache
Normal 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;
|
||||
255
wo/cli/templates/anemometer.mustache
Normal file
255
wo/cli/templates/anemometer.mustache
Normal 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'
|
||||
),
|
||||
);
|
||||
|
||||
?>
|
||||
2
wo/cli/templates/blockips.mustache
Normal file
2
wo/cli/templates/blockips.mustache
Normal file
@@ -0,0 +1,2 @@
|
||||
# Block IP Address
|
||||
# deny 1.1.1.1;
|
||||
10
wo/cli/templates/fastcgi.mustache
Normal file
10
wo/cli/templates/fastcgi.mustache
Normal 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;
|
||||
10
wo/cli/templates/info_mysql.mustache
Normal file
10
wo/cli/templates/info_mysql.mustache
Normal 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
|
||||
10
wo/cli/templates/info_nginx.mustache
Normal file
10
wo/cli/templates/info_nginx.mustache
Normal 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}}
|
||||
35
wo/cli/templates/info_php.mustache
Normal file
35
wo/cli/templates/info_php.mustache
Normal 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}}
|
||||
68
wo/cli/templates/locations-php7.mustache
Normal file
68
wo/cli/templates/locations-php7.mustache
Normal 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;
|
||||
}
|
||||
68
wo/cli/templates/locations.mustache
Normal file
68
wo/cli/templates/locations.mustache
Normal 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;
|
||||
}
|
||||
60
wo/cli/templates/nginx-core.mustache
Normal file
60
wo/cli/templates/nginx-core.mustache
Normal 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
|
||||
5
wo/cli/templates/php-fpm.mustache
Normal file
5
wo/cli/templates/php-fpm.mustache
Normal file
@@ -0,0 +1,5 @@
|
||||
[global]
|
||||
pid = {{pid}}
|
||||
error_log = {{error_log}}
|
||||
log_level = notice
|
||||
include = {{include}}
|
||||
10
wo/cli/templates/php-hhvm.mustache
Normal file
10
wo/cli/templates/php-hhvm.mustache
Normal 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;
|
||||
}
|
||||
10
wo/cli/templates/php.mustache
Normal file
10
wo/cli/templates/php.mustache
Normal 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;
|
||||
}
|
||||
10
wo/cli/templates/php7.mustache
Normal file
10
wo/cli/templates/php7.mustache
Normal 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;
|
||||
}
|
||||
58
wo/cli/templates/redis-hhvm.mustache
Normal file
58
wo/cli/templates/redis-hhvm.mustache
Normal 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;
|
||||
}
|
||||
56
wo/cli/templates/redis-php7.mustache
Normal file
56
wo/cli/templates/redis-php7.mustache
Normal 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;
|
||||
}
|
||||
57
wo/cli/templates/redis.mustache
Normal file
57
wo/cli/templates/redis.mustache
Normal 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;
|
||||
}
|
||||
15
wo/cli/templates/siteinfo.mustache
Normal file
15
wo/cli/templates/siteinfo.mustache
Normal 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}}
|
||||
26
wo/cli/templates/upstream.mustache
Normal file
26
wo/cli/templates/upstream.mustache
Normal 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}}
|
||||
47
wo/cli/templates/virtualconf-php7.mustache
Normal file
47
wo/cli/templates/virtualconf-php7.mustache
Normal 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}}
|
||||
}
|
||||
46
wo/cli/templates/virtualconf.mustache
Normal file
46
wo/cli/templates/virtualconf.mustache
Normal 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}}
|
||||
}
|
||||
83
wo/cli/templates/wo-plus.mustache
Normal file
83
wo/cli/templates/wo-plus.mustache
Normal 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;
|
||||
21
wo/cli/templates/wpcommon-php7.mustache
Normal file
21
wo/cli/templates/wpcommon-php7.mustache
Normal 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;
|
||||
}
|
||||
}
|
||||
21
wo/cli/templates/wpcommon.mustache
Normal file
21
wo/cli/templates/wpcommon.mustache
Normal 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;
|
||||
}
|
||||
}
|
||||
37
wo/cli/templates/wpfc-hhvm.mustache
Normal file
37
wo/cli/templates/wpfc-hhvm.mustache
Normal 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;
|
||||
}
|
||||
37
wo/cli/templates/wpfc-php7.mustache
Normal file
37
wo/cli/templates/wpfc-php7.mustache
Normal 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;
|
||||
}
|
||||
37
wo/cli/templates/wpfc.mustache
Normal file
37
wo/cli/templates/wpfc.mustache
Normal 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;
|
||||
}
|
||||
31
wo/cli/templates/wpsc-hhvm.mustache
Normal file
31
wo/cli/templates/wpsc-hhvm.mustache
Normal 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;
|
||||
}
|
||||
31
wo/cli/templates/wpsc-php7.mustache
Normal file
31
wo/cli/templates/wpsc-php7.mustache
Normal 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;
|
||||
}
|
||||
31
wo/cli/templates/wpsc.mustache
Normal file
31
wo/cli/templates/wpsc.mustache
Normal 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;
|
||||
}
|
||||
10
wo/cli/templates/wpsubdir.mustache
Normal file
10
wo/cli/templates/wpsubdir.mustache
Normal 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;
|
||||
}
|
||||
0
wo/core/__init__.py
Normal file
0
wo/core/__init__.py
Normal file
48
wo/core/addswap.py
Normal file
48
wo/core/addswap.py
Normal file
@@ -0,0 +1,48 @@
|
||||
"""WordOps Swap Creation"""
|
||||
from wo.core.variables import WOVariables
|
||||
from wo.core.shellexec import WOShellExec
|
||||
from wo.core.fileutils import WOFileUtils
|
||||
from wo.core.aptget import WOAptGet
|
||||
from wo.core.logging import Log
|
||||
import os
|
||||
|
||||
|
||||
class WOSwap():
|
||||
"""Manage Swap"""
|
||||
|
||||
def __init__():
|
||||
"""Initialize """
|
||||
pass
|
||||
|
||||
def add(self):
|
||||
"""Swap addition with WordOps"""
|
||||
if WOVariables.wo_ram < 512:
|
||||
if WOVariables.wo_swap < 1000:
|
||||
Log.info(self, "Adding SWAP file, please wait...")
|
||||
|
||||
# Install dphys-swapfile
|
||||
WOAptGet.update(self)
|
||||
WOAptGet.install(self, ["dphys-swapfile"])
|
||||
# Stop service
|
||||
WOShellExec.cmd_exec(self, "service dphys-swapfile stop")
|
||||
# Remove Default swap created
|
||||
WOShellExec.cmd_exec(self, "/sbin/dphys-swapfile uninstall")
|
||||
|
||||
# Modify Swap configuration
|
||||
if os.path.isfile("/etc/dphys-swapfile"):
|
||||
WOFileUtils.searchreplace(self, "/etc/dphys-swapfile",
|
||||
"#CONF_SWAPFILE=/var/swap",
|
||||
"CONF_SWAPFILE=/wo-swapfile")
|
||||
WOFileUtils.searchreplace(self, "/etc/dphys-swapfile",
|
||||
"#CONF_MAXSWAP=2048",
|
||||
"CONF_MAXSWAP=1024")
|
||||
WOFileUtils.searchreplace(self, "/etc/dphys-swapfile",
|
||||
"#CONF_SWAPSIZE=",
|
||||
"CONF_SWAPSIZE=1024")
|
||||
else:
|
||||
with open("/etc/dphys-swapfile", 'w') as conffile:
|
||||
conffile.write("CONF_SWAPFILE=/wo-swapfile\n"
|
||||
"CONF_SWAPSIZE=1024\n"
|
||||
"CONF_MAXSWAP=1024\n")
|
||||
# Create swap file
|
||||
WOShellExec.cmd_exec(self, "service dphys-swapfile start")
|
||||
91
wo/core/apt_repo.py
Normal file
91
wo/core/apt_repo.py
Normal file
@@ -0,0 +1,91 @@
|
||||
"""WordOps packages repository operations"""
|
||||
from wo.core.shellexec import WOShellExec
|
||||
from wo.core.variables import WOVariables
|
||||
from wo.core.logging import Log
|
||||
import os
|
||||
|
||||
|
||||
class WORepo():
|
||||
"""Manage Repositories"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize """
|
||||
pass
|
||||
|
||||
def add(self, repo_url=None, ppa=None):
|
||||
"""
|
||||
This function used to add apt repositories and or ppa's
|
||||
If repo_url is provided adds repo file to
|
||||
/etc/apt/sources.list.d/
|
||||
If ppa is provided add apt-repository using
|
||||
add-apt-repository
|
||||
command.
|
||||
"""
|
||||
|
||||
if repo_url is not None:
|
||||
repo_file_path = ("/etc/apt/sources.list.d/"
|
||||
+ WOVariables().wo_repo_file)
|
||||
try:
|
||||
if not os.path.isfile(repo_file_path):
|
||||
with open(repo_file_path,
|
||||
encoding='utf-8', mode='a') as repofile:
|
||||
repofile.write(repo_url)
|
||||
repofile.write('\n')
|
||||
repofile.close()
|
||||
elif repo_url not in open(repo_file_path,
|
||||
encoding='utf-8').read():
|
||||
with open(repo_file_path,
|
||||
encoding='utf-8', mode='a') as repofile:
|
||||
repofile.write(repo_url)
|
||||
repofile.write('\n')
|
||||
repofile.close()
|
||||
return True
|
||||
except IOError as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "File I/O error.")
|
||||
except Exception as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to add repo")
|
||||
if ppa is not None:
|
||||
WOShellExec.cmd_exec(self, "add-apt-repository -y '{ppa_name}'"
|
||||
.format(ppa_name=ppa))
|
||||
|
||||
def remove(self, ppa=None, repo_url=None):
|
||||
"""
|
||||
This function used to remove ppa's
|
||||
If ppa is provided adds repo file to
|
||||
/etc/apt/sources.list.d/
|
||||
command.
|
||||
"""
|
||||
if ppa:
|
||||
WOShellExec.cmd_exec(self, "add-apt-repository -y "
|
||||
"--remove '{ppa_name}'"
|
||||
.format(ppa_name=ppa))
|
||||
elif repo_url:
|
||||
repo_file_path = ("/etc/apt/sources.list.d/"
|
||||
+ WOVariables().wo_repo_file)
|
||||
|
||||
try:
|
||||
repofile = open(repo_file_path, "w+")
|
||||
repofile.write(repofile.read().replace(repo_url, ""))
|
||||
repofile.close()
|
||||
except IOError as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "File I/O error.")
|
||||
except Exception as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to remove repo")
|
||||
|
||||
def add_key(self, keyids, keyserver=None):
|
||||
"""
|
||||
This function adds imports repository keys from keyserver.
|
||||
default keyserver is hkp://keys.gnupg.net
|
||||
user can provide other keyserver with keyserver="hkp://xyz"
|
||||
"""
|
||||
WOShellExec.cmd_exec(self, "gpg --keyserver {serv}"
|
||||
.format(serv=(keyserver or
|
||||
"hkp://keys.gnupg.net"))
|
||||
+ " --recv-keys {key}".format(key=keyids))
|
||||
WOShellExec.cmd_exec(self, "gpg -a --export --armor {0}"
|
||||
.format(keyids)
|
||||
+ " | apt-key add - ")
|
||||
231
wo/core/aptget.py
Normal file
231
wo/core/aptget.py
Normal file
@@ -0,0 +1,231 @@
|
||||
"""WordOps package installation using apt-get module."""
|
||||
import apt
|
||||
import apt_pkg
|
||||
import sys
|
||||
import subprocess
|
||||
from wo.core.logging import Log
|
||||
from wo.core.apt_repo import WORepo
|
||||
from sh import apt_get
|
||||
from sh import ErrorReturnCode
|
||||
|
||||
|
||||
class WOAptGet():
|
||||
"""Generic apt-get intialisation"""
|
||||
|
||||
def update(self):
|
||||
"""
|
||||
Similar to `apt-get update`
|
||||
"""
|
||||
try:
|
||||
with open('/var/log/wo/wordops.log', 'a') as f:
|
||||
proc = subprocess.Popen('apt-get update',
|
||||
shell=True,
|
||||
stdin=None, stdout=f,
|
||||
stderr=subprocess.PIPE,
|
||||
executable="/bin/bash")
|
||||
proc.wait()
|
||||
output, error_output = proc.communicate()
|
||||
|
||||
# Check what is error in error_output
|
||||
if "NO_PUBKEY" in str(error_output):
|
||||
# Split the output
|
||||
Log.info(self, "Fixing missing GPG keys, please wait...")
|
||||
error_list = str(error_output).split("\\n")
|
||||
|
||||
# Use a loop to add misising keys
|
||||
for single_error in error_list:
|
||||
if "NO_PUBKEY" in single_error:
|
||||
key = single_error.rsplit(None, 1)[-1]
|
||||
WORepo.add_key(self, key, keyserver="hkp://pgp.mit.edu")
|
||||
|
||||
proc = subprocess.Popen('apt-get update',
|
||||
shell=True,
|
||||
stdin=None, stdout=f, stderr=f,
|
||||
executable="/bin/bash")
|
||||
proc.wait()
|
||||
|
||||
if proc.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
Log.info(self, Log.FAIL + "Whoops, something went wrong...")
|
||||
Log.error(self, "Check the WordOps log for more details "
|
||||
"`tail /var/log/wo/wordops.log` and please try again...")
|
||||
|
||||
except Exception as e:
|
||||
Log.error(self, "apt-get update exited with error")
|
||||
|
||||
def check_upgrade(self):
|
||||
"""
|
||||
Similar to `apt-get upgrade`
|
||||
"""
|
||||
try:
|
||||
check_update = subprocess.Popen(['apt-get upgrade -s | grep '
|
||||
'\"^Inst\" | wc -l'],
|
||||
stdout=subprocess.PIPE,
|
||||
shell=True).communicate()[0]
|
||||
if check_update == b'0\n':
|
||||
Log.error(self, "No package updates available")
|
||||
Log.info(self, "Following package updates are available:")
|
||||
subprocess.Popen("apt-get -s dist-upgrade | grep \"^Inst\"",
|
||||
shell=True, executable="/bin/bash",
|
||||
stdout=sys.stdout).communicate()
|
||||
|
||||
except Exception as e:
|
||||
Log.error(self, "Unable to check for packages upgrades")
|
||||
|
||||
def dist_upgrade(self):
|
||||
"""
|
||||
Similar to `apt-get upgrade`
|
||||
"""
|
||||
try:
|
||||
with open('/var/log/wo/wordops.log', 'a') as f:
|
||||
proc = subprocess.Popen("DEBIAN_FRONTEND=noninteractive "
|
||||
"apt-get dist-upgrade -o "
|
||||
"Dpkg::Options::=\"--force-confdef\""
|
||||
" -o "
|
||||
"Dpkg::Options::=\"--force-confold\""
|
||||
" -y ",
|
||||
shell=True, stdin=None,
|
||||
stdout=f, stderr=f,
|
||||
executable="/bin/bash")
|
||||
proc.wait()
|
||||
|
||||
if proc.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
Log.info(self, Log.FAIL + "Oops Something went "
|
||||
"wrong!!")
|
||||
Log.error(self, "Check the WordOps log for more details "
|
||||
"`tail /var/log/wo/wordops.log` and please try again...")
|
||||
except Exception as e:
|
||||
Log.error(self, "Error while installing packages, "
|
||||
"apt-get exited with error")
|
||||
|
||||
def install(self, packages):
|
||||
all_packages = ' '.join(packages)
|
||||
try:
|
||||
with open('/var/log/wo/wordops.log', 'a') as f:
|
||||
proc = subprocess.Popen("DEBIAN_FRONTEND=noninteractive "
|
||||
"apt-get install -o "
|
||||
"Dpkg::Options::=\"--force-confdef\""
|
||||
" -o "
|
||||
"Dpkg::Options::=\"--force-confold\""
|
||||
" -y --allow-unauthenticated {0}"
|
||||
.format(all_packages), shell=True,
|
||||
stdin=None, stdout=f, stderr=f,
|
||||
executable="/bin/bash")
|
||||
proc.wait()
|
||||
|
||||
if proc.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
Log.info(self, Log.FAIL + "Oops Something went "
|
||||
"wrong!!")
|
||||
Log.error(self, "Check the WordOps log for more details "
|
||||
"`tail /var/log/wo/wordops.log` and please try again...")
|
||||
|
||||
except Exception as e:
|
||||
Log.info(self, Log.FAIL + "Oops Something went "
|
||||
"wrong!!")
|
||||
Log.error(self, "Check the WordOps log for more details "
|
||||
"`tail /var/log/wo/wordops.log` and please try again...")
|
||||
|
||||
def remove(self, packages, auto=False, purge=False):
|
||||
all_packages = ' '.join(packages)
|
||||
try:
|
||||
with open('/var/log/wo/wordops.log', 'a') as f:
|
||||
if purge:
|
||||
proc = subprocess.Popen('apt-get purge -y {0}'
|
||||
.format(all_packages), shell=True,
|
||||
stdin=None, stdout=f, stderr=f,
|
||||
executable="/bin/bash")
|
||||
else:
|
||||
proc = subprocess.Popen('apt-get remove -y {0}'
|
||||
.format(all_packages), shell=True,
|
||||
stdin=None, stdout=f, stderr=f,
|
||||
executable="/bin/bash")
|
||||
proc.wait()
|
||||
if proc.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
Log.info(self, Log.FAIL + "Oops Something went "
|
||||
"wrong!!")
|
||||
Log.error(self, "Check the WordOps log for more details "
|
||||
"`tail /var/log/wo/wordops.log` and please try again...")
|
||||
|
||||
except Exception as e:
|
||||
Log.error(self, "Error while installing packages, "
|
||||
"apt-get exited with error")
|
||||
|
||||
def auto_clean(self):
|
||||
"""
|
||||
Similar to `apt-get autoclean`
|
||||
"""
|
||||
try:
|
||||
orig_out = sys.stdout
|
||||
sys.stdout = open(self.app.config.get('log.logging', 'file'),
|
||||
encoding='utf-8', mode='a')
|
||||
apt_get.autoclean("-y")
|
||||
sys.stdout = orig_out
|
||||
except ErrorReturnCode as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to apt-get autoclean")
|
||||
|
||||
def auto_remove(self):
|
||||
"""
|
||||
Similar to `apt-get autoremove`
|
||||
"""
|
||||
try:
|
||||
Log.debug(self, "Running apt-get autoremove")
|
||||
apt_get.autoremove("-y")
|
||||
except ErrorReturnCode as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to apt-get autoremove")
|
||||
|
||||
def is_installed(self, package_name):
|
||||
"""
|
||||
Checks if package is available in cache and is installed or not
|
||||
returns True if installed otherwise returns False
|
||||
"""
|
||||
apt_cache = apt.cache.Cache()
|
||||
apt_cache.open()
|
||||
if (package_name.strip() in apt_cache and
|
||||
apt_cache[package_name.strip()].is_installed):
|
||||
# apt_cache.close()
|
||||
return True
|
||||
# apt_cache.close()
|
||||
return False
|
||||
|
||||
def download_only(self,package_name,repo_url=None,repo_key=None):
|
||||
"""
|
||||
Similar to `apt-get install --download-only PACKAGE_NAME`
|
||||
"""
|
||||
packages = ' '.join(package_name)
|
||||
try:
|
||||
with open('/var/log/wo/wordops.log', 'a') as f:
|
||||
if repo_url is not None:
|
||||
WORepo.add(self, repo_url=repo_url)
|
||||
if repo_key is not None:
|
||||
WORepo.add_key(self, repo_key)
|
||||
proc = subprocess.Popen("apt-get update && DEBIAN_FRONTEND=noninteractive "
|
||||
"apt-get install -o "
|
||||
"Dpkg::Options::=\"--force-confdef\""
|
||||
" -o "
|
||||
"Dpkg::Options::=\"--force-confold\""
|
||||
" -y --download-only {0}"
|
||||
.format(packages), shell=True,
|
||||
stdin=None, stdout=f, stderr=f,
|
||||
executable="/bin/bash")
|
||||
proc.wait()
|
||||
|
||||
if proc.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
Log.error(self,"Error in fetching dpkg package.\nReverting changes ..",False)
|
||||
if repo_url is not None:
|
||||
WORepo.remove(self, repo_url=repo_url)
|
||||
return False
|
||||
except Exception as e:
|
||||
Log.error(self, "Error while downloading packages, "
|
||||
"apt-get exited with error")
|
||||
|
||||
23
wo/core/checkfqdn.py
Normal file
23
wo/core/checkfqdn.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from wo.core.shellexec import WOShellExec
|
||||
from wo.core.variables import WOVariables
|
||||
import os
|
||||
|
||||
|
||||
def check_fqdn(self, wo_host):
|
||||
"""FQDN check with WordOps, for mail server hostname must be FQDN"""
|
||||
# wo_host=os.popen("hostname -f | tr -d '\n'").read()
|
||||
if '.' in wo_host:
|
||||
WOVariables.wo_fqdn = wo_host
|
||||
with open('/etc/hostname', encoding='utf-8', mode='w') as hostfile:
|
||||
hostfile.write(wo_host)
|
||||
|
||||
WOShellExec.cmd_exec(self, "sed -i \"1i\\127.0.0.1 {0}\" /etc/hosts"
|
||||
.format(wo_host))
|
||||
if WOVariables.wo_platform_distro == 'debian':
|
||||
WOShellExec.cmd_exec(self, "/etc/init.d/hostname.sh start")
|
||||
else:
|
||||
WOShellExec.cmd_exec(self, "service hostname restart")
|
||||
|
||||
else:
|
||||
wo_host = input("Enter hostname [fqdn]:")
|
||||
check_fqdn(self, wo_host)
|
||||
32
wo/core/cron.py
Normal file
32
wo/core/cron.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from wo.core.shellexec import WOShellExec
|
||||
from wo.core.logging import Log
|
||||
|
||||
"""
|
||||
Set CRON on LINUX system.
|
||||
"""
|
||||
|
||||
class WOCron():
|
||||
def setcron_weekly(self,cmd,comment='Cron set by WordOps',user='root',min=0,hour=12):
|
||||
if not WOShellExec.cmd_exec(self, "crontab -l | grep -q \'{0}\'".format(cmd)):
|
||||
|
||||
WOShellExec.cmd_exec(self, "/bin/bash -c \"crontab -l "
|
||||
"2> /dev/null | {{ cat; echo -e"
|
||||
" \\\""
|
||||
"\\n0 0 * * 0 "
|
||||
"{0}".format(cmd) +
|
||||
" # {0}".format(comment)+
|
||||
"\\\"; } | crontab -\"")
|
||||
Log.debug(self, "Cron set")
|
||||
|
||||
|
||||
|
||||
def remove_cron(self,cmd):
|
||||
if WOShellExec.cmd_exec(self, "crontab -l | grep -q \'{0}\'".format(cmd)):
|
||||
if not WOShellExec.cmd_exec(self, "/bin/bash -c "
|
||||
"\"crontab "
|
||||
"-l | sed '/{0}/d'"
|
||||
"| crontab -\""
|
||||
.format(cmd)):
|
||||
Log.error(self, "Failed to remove crontab entry",False)
|
||||
else:
|
||||
Log.debug(self, "Cron not found")
|
||||
28
wo/core/database.py
Normal file
28
wo/core/database.py
Normal file
@@ -0,0 +1,28 @@
|
||||
"""WordOps generic database creation module"""
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import scoped_session, sessionmaker
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from wo.core.variables import WOVariables
|
||||
|
||||
# db_path = self.app.config.get('site', 'db_path')
|
||||
engine = create_engine(WOVariables.wo_db_uri, convert_unicode=True)
|
||||
db_session = scoped_session(sessionmaker(autocommit=False,
|
||||
autoflush=False,
|
||||
bind=engine))
|
||||
Base = declarative_base()
|
||||
Base.query = db_session.query_property()
|
||||
|
||||
|
||||
def init_db(app):
|
||||
"""
|
||||
Initializes and creates all tables from models into the database
|
||||
"""
|
||||
# import all modules here that might define models so that
|
||||
# they will be registered properly on the metadata. Otherwise
|
||||
# # you will have to import them first before calling init_db()
|
||||
# import wo.core.models
|
||||
try:
|
||||
app.log.info("Initializing WordOps Database")
|
||||
Base.metadata.create_all(bind=engine)
|
||||
except Exception as e:
|
||||
app.log.debug("{0}".format(e))
|
||||
24
wo/core/domainvalidate.py
Normal file
24
wo/core/domainvalidate.py
Normal file
@@ -0,0 +1,24 @@
|
||||
"""WordOps domain validation module."""
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
||||
def ValidateDomain(url):
|
||||
"""
|
||||
This function returns domain name removing http:// and https://
|
||||
returns domain name only with or without www as user provided.
|
||||
"""
|
||||
|
||||
# Check if http:// or https:// present remove it if present
|
||||
domain_name = url.split('/')
|
||||
if 'http:' in domain_name or 'https:' in domain_name:
|
||||
domain_name = domain_name[2]
|
||||
else:
|
||||
domain_name = domain_name[0]
|
||||
www_domain_name = domain_name.split('.')
|
||||
final_domain = ''
|
||||
if www_domain_name[0] == 'www':
|
||||
final_domain = '.'.join(www_domain_name[1:])
|
||||
else:
|
||||
final_domain = domain_name
|
||||
|
||||
return (final_domain, domain_name)
|
||||
45
wo/core/download.py
Normal file
45
wo/core/download.py
Normal file
@@ -0,0 +1,45 @@
|
||||
"""WordOps download core classes."""
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
import os
|
||||
from wo.core.logging import Log
|
||||
|
||||
|
||||
class WODownload():
|
||||
"""Method to download using urllib"""
|
||||
def __init__():
|
||||
pass
|
||||
|
||||
def download(self, packages):
|
||||
"""Download packages, packges must be list in format of
|
||||
[url, path, package name]"""
|
||||
for package in packages:
|
||||
url = package[0]
|
||||
filename = package[1]
|
||||
pkg_name = package[2]
|
||||
try:
|
||||
directory = os.path.dirname(filename)
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
Log.info(self, "Downloading {0:20}".format(pkg_name), end=' ')
|
||||
req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
|
||||
with urllib.request.urlopen(req) as response, open(filename, 'wb') as out_file:
|
||||
out_file.write(response.read())
|
||||
Log.info(self, "{0}".format("[" + Log.ENDC + "Done"
|
||||
+ Log.OKBLUE + "]"))
|
||||
except urllib.error.URLError as e:
|
||||
Log.debug(self, "[{err}]".format(err=str(e.reason)))
|
||||
Log.error(self, "Unable to download file, {0}"
|
||||
.format(filename))
|
||||
return False
|
||||
except urllib.error.HTTPError as e:
|
||||
Log.error(self, "Package download failed. {0}"
|
||||
.format(pkg_name))
|
||||
Log.debug(self, "[{err}]".format(err=str(e.reason)))
|
||||
return False
|
||||
except urllib.error.ContentTooShortError as e:
|
||||
Log.debug(self, "{0}{1}".format(e.errno, e.strerror))
|
||||
Log.error(self, "Package download failed. The amount of the"
|
||||
" downloaded data is less than "
|
||||
"the expected amount \{0} ".format(pkg_name))
|
||||
return False
|
||||
26
wo/core/exc.py
Normal file
26
wo/core/exc.py
Normal file
@@ -0,0 +1,26 @@
|
||||
"""WordOps exception classes."""
|
||||
|
||||
|
||||
class WOError(Exception):
|
||||
"""Generic errors."""
|
||||
def __init__(self, msg):
|
||||
Exception.__init__(self)
|
||||
self.msg = msg
|
||||
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
|
||||
class WOConfigError(WOError):
|
||||
"""Config related errors."""
|
||||
pass
|
||||
|
||||
|
||||
class WORuntimeError(WOError):
|
||||
"""Generic runtime errors."""
|
||||
pass
|
||||
|
||||
|
||||
class WOArgumentError(WOError):
|
||||
"""Argument related errors."""
|
||||
pass
|
||||
21
wo/core/extract.py
Normal file
21
wo/core/extract.py
Normal file
@@ -0,0 +1,21 @@
|
||||
"""WordOps Extract Core """
|
||||
import tarfile
|
||||
import os
|
||||
from wo.core.logging import Log
|
||||
|
||||
|
||||
class WOExtract():
|
||||
"""Method to extract from tar.gz file"""
|
||||
|
||||
def extract(self, file, path):
|
||||
"""Function to extract tar.gz file"""
|
||||
try:
|
||||
tar = tarfile.open(file)
|
||||
tar.extractall(path=path)
|
||||
tar.close()
|
||||
os.remove(file)
|
||||
return True
|
||||
except tarfile.TarError as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, 'Unable to extract file \{0}'.format(file))
|
||||
return False
|
||||
268
wo/core/fileutils.py
Normal file
268
wo/core/fileutils.py
Normal file
@@ -0,0 +1,268 @@
|
||||
"""WordOps file utils core classes."""
|
||||
import shutil
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
import shutil
|
||||
import pwd
|
||||
import fileinput
|
||||
from wo.core.logging import Log
|
||||
|
||||
|
||||
class WOFileUtils():
|
||||
"""Utilities to operate on files"""
|
||||
def __init__():
|
||||
pass
|
||||
|
||||
def remove(self, filelist):
|
||||
"""remove files from given path"""
|
||||
for file in filelist:
|
||||
if os.path.isfile(file):
|
||||
Log.info(self, "Removing {0:65}".format(file), end=' ')
|
||||
os.remove(file)
|
||||
Log.info(self, "{0}".format("[" + Log.ENDC + "Done" +
|
||||
Log.OKBLUE + "]"))
|
||||
Log.debug(self, 'file Removed')
|
||||
if os.path.isdir(file):
|
||||
try:
|
||||
Log.info(self, "Removing {0:65}".format(file), end=' ')
|
||||
shutil.rmtree(file)
|
||||
Log.info(self, "{0}".format("[" + Log.ENDC + "Done" +
|
||||
Log.OKBLUE + "]"))
|
||||
except shutil.Error as e:
|
||||
Log.debug(self, "{err}".format(err=str(e.reason)))
|
||||
Log.error(self, 'Unable to Remove file ')
|
||||
|
||||
def create_symlink(self, paths, errormsg=''):
|
||||
"""
|
||||
Create symbolic links provided in list with first as source
|
||||
and second as destination
|
||||
"""
|
||||
src = paths[0]
|
||||
dst = paths[1]
|
||||
if not os.path.islink(dst):
|
||||
try:
|
||||
Log.debug(self, "Creating Symbolic link, Source:{0}, Dest:{1}"
|
||||
.format(src, dst))
|
||||
os.symlink(src, dst)
|
||||
except Exception as e:
|
||||
Log.debug(self, "{0}{1}".format(e.errno, e.strerror))
|
||||
Log.error(self, "Unable to create symbolic link ...\n ")
|
||||
else:
|
||||
Log.debug(self, "Destination: {0} exists".format(dst))
|
||||
|
||||
def remove_symlink(self, filepath):
|
||||
"""
|
||||
Removes symbolic link for the path provided with filepath
|
||||
"""
|
||||
try:
|
||||
Log.debug(self, "Removing symbolic link: {0}".format(filepath))
|
||||
os.unlink(filepath)
|
||||
except Exception as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to reomove symbolic link ...\n")
|
||||
|
||||
def copyfiles(self, src, dest):
|
||||
"""
|
||||
Copies files:
|
||||
src : source path
|
||||
dest : destination path
|
||||
|
||||
Recursively copy an entire directory tree rooted at src.
|
||||
The destination directory, named by dst, must not already exist;
|
||||
it will be created as well as missing parent directories.
|
||||
"""
|
||||
try:
|
||||
Log.debug(self, "Copying files, Source:{0}, Dest:{1}"
|
||||
.format(src, dest))
|
||||
shutil.copytree(src, dest)
|
||||
except shutil.Error as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, 'Unable to copy files from {0} to {1}'
|
||||
.format(src, dest))
|
||||
except IOError as e:
|
||||
Log.debug(self, "{0}".format(e.strerror))
|
||||
Log.error(self, "Unable to copy files from {0} to {1}"
|
||||
.format(src, dest))
|
||||
|
||||
def copyfile(self, src, dest):
|
||||
"""
|
||||
Copy file:
|
||||
src : source path
|
||||
dest : destination path
|
||||
"""
|
||||
try:
|
||||
Log.debug(self, "Copying file, Source:{0}, Dest:{1}"
|
||||
.format(src, dest))
|
||||
shutil.copy2(src, dest)
|
||||
except shutil.Error as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, 'Unable to copy file from {0} to {1}'
|
||||
.format(src, dest))
|
||||
except IOError as e:
|
||||
Log.debug(self, "{0}".format(e.strerror))
|
||||
Log.error(self, "Unable to copy file from {0} to {1}"
|
||||
.format(src, dest))
|
||||
|
||||
def searchreplace(self, fnm, sstr, rstr):
|
||||
"""
|
||||
Search replace strings in file
|
||||
fnm : filename
|
||||
sstr: search string
|
||||
rstr: replace string
|
||||
"""
|
||||
try:
|
||||
Log.debug(self, "Doning search and replace, File:{0},"
|
||||
"Source string:{1}, Dest String:{2}"
|
||||
.format(fnm, sstr, rstr))
|
||||
for line in fileinput.input(fnm, inplace=True):
|
||||
print(line.replace(sstr, rstr), end='')
|
||||
fileinput.close()
|
||||
except Exception as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to search {0} and replace {1} {2}"
|
||||
.format(fnm, sstr, rstr))
|
||||
|
||||
def mvfile(self, src, dst):
|
||||
"""
|
||||
Moves file from source path to destination path
|
||||
src : source path
|
||||
dst : Destination path
|
||||
"""
|
||||
try:
|
||||
Log.debug(self, "Moving file from {0} to {1}".format(src, dst))
|
||||
shutil.move(src, dst)
|
||||
except Exception as e:
|
||||
Log.debug(self, "{err}".format(err=e))
|
||||
Log.error(self, 'Unable to move file from {0} to {1}'
|
||||
.format(src, dst))
|
||||
|
||||
def chdir(self, path):
|
||||
"""
|
||||
Change Directory to path specified
|
||||
Path : path for destination directory
|
||||
"""
|
||||
try:
|
||||
Log.debug(self, "Changing directory to {0}"
|
||||
.format(path))
|
||||
os.chdir(path)
|
||||
except OSError as e:
|
||||
Log.debug(self, "{err}".format(err=e.strerror))
|
||||
Log.error(self, 'Unable to Change Directory {0}'.format(path))
|
||||
|
||||
def chown(self, path, user, group, recursive=False):
|
||||
"""
|
||||
Change Owner for files
|
||||
change owner for file with path specified
|
||||
user: username of owner
|
||||
group: group of owner
|
||||
recursive: if recursive is True change owner for all
|
||||
files in directory
|
||||
"""
|
||||
userid = pwd.getpwnam(user)[2]
|
||||
groupid = pwd.getpwnam(user)[3]
|
||||
try:
|
||||
Log.debug(self, "Changing ownership of {0}, Userid:{1},Groupid:{2}"
|
||||
.format(path, userid, groupid))
|
||||
# Change inside files/directory permissions only if recursive flag
|
||||
# is set
|
||||
if recursive:
|
||||
for root, dirs, files in os.walk(path):
|
||||
for d in dirs:
|
||||
os.chown(os.path.join(root, d), userid,
|
||||
groupid)
|
||||
for f in files:
|
||||
os.chown(os.path.join(root, f), userid,
|
||||
groupid)
|
||||
os.chown(path, userid, groupid)
|
||||
except shutil.Error as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to change owner : {0}".format(path))
|
||||
except Exception as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to change owner : {0} ".format(path))
|
||||
|
||||
def chmod(self, path, perm, recursive=False):
|
||||
"""
|
||||
Changes Permission for files
|
||||
path : file path permission to be changed
|
||||
perm : permissions to be given
|
||||
recursive: change permission recursively for all files
|
||||
"""
|
||||
try:
|
||||
Log.debug(self, "Changing permission of {0}, Perm:{1}"
|
||||
.format(path, perm))
|
||||
if recursive:
|
||||
for root, dirs, files in os.walk(path):
|
||||
for d in dirs:
|
||||
os.chmod(os.path.join(root, d), perm)
|
||||
for f in files:
|
||||
os.chmod(os.path.join(root, f), perm)
|
||||
else:
|
||||
os.chmod(path, perm)
|
||||
except OSError as e:
|
||||
Log.debug(self, "{0}".format(e.strerror))
|
||||
Log.error(self, "Unable to change owner : {0}".format(path))
|
||||
|
||||
def mkdir(self, path):
|
||||
"""
|
||||
create directories.
|
||||
path : path for directory to be created
|
||||
Similar to `mkdir -p`
|
||||
"""
|
||||
try:
|
||||
Log.debug(self, "Creating directories: {0}"
|
||||
.format(path))
|
||||
os.makedirs(path)
|
||||
except OSError as e:
|
||||
Log.debug(self, "{0}".format(e.strerror))
|
||||
Log.error(self, "Unable to create directory {0} ".format(path))
|
||||
|
||||
def isexist(self, path):
|
||||
"""
|
||||
Check if file exist on given path
|
||||
"""
|
||||
try:
|
||||
if os.path.exists(path):
|
||||
return (True)
|
||||
else:
|
||||
return (False)
|
||||
except OSError as e:
|
||||
Log.debug(self, "{0}".format(e.strerror))
|
||||
Log.error(self, "Unable to check path {0}".format(path))
|
||||
|
||||
def grep(self, fnm, sstr):
|
||||
"""
|
||||
Searches for string in file and returns the matched line.
|
||||
"""
|
||||
try:
|
||||
Log.debug(self, "Finding string {0} to file {1}"
|
||||
.format(sstr, fnm))
|
||||
for line in open(fnm, encoding='utf-8'):
|
||||
if sstr in line:
|
||||
return line
|
||||
return False
|
||||
except OSError as e:
|
||||
Log.debug(self, "{0}".format(e.strerror))
|
||||
Log.error(self, "Unable to Search string {0} in {1}"
|
||||
.format(sstr, fnm))
|
||||
|
||||
def rm(self, path):
|
||||
"""
|
||||
Remove files
|
||||
"""
|
||||
Log.debug(self, "Removing {0}".format(path))
|
||||
if WOFileUtils.isexist(self, path):
|
||||
try:
|
||||
if os.path.isdir(path):
|
||||
shutil.rmtree(path)
|
||||
else:
|
||||
os.remove(path)
|
||||
except shutil.Error as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to remove directory : {0} "
|
||||
.format(path))
|
||||
except OSError as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to remove file : {0} "
|
||||
.format(path))
|
||||
57
wo/core/git.py
Normal file
57
wo/core/git.py
Normal file
@@ -0,0 +1,57 @@
|
||||
"""WordOps GIT module"""
|
||||
from sh import git, ErrorReturnCode
|
||||
from wo.core.logging import Log
|
||||
import os
|
||||
|
||||
|
||||
class WOGit:
|
||||
"""Intialization of core variables"""
|
||||
def ___init__():
|
||||
# TODO method for core variables
|
||||
pass
|
||||
|
||||
def add(self, paths, msg="Intializating"):
|
||||
"""
|
||||
Initializes Directory as repository if not already git repo.
|
||||
and adds uncommited changes automatically
|
||||
"""
|
||||
for path in paths:
|
||||
global git
|
||||
git = git.bake("--git-dir={0}/.git".format(path),
|
||||
"--work-tree={0}".format(path))
|
||||
if os.path.isdir(path):
|
||||
if not os.path.isdir(path+"/.git"):
|
||||
try:
|
||||
Log.debug(self, "WOGit: git init at {0}"
|
||||
.format(path))
|
||||
git.init(path)
|
||||
except ErrorReturnCode as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to git init at {0}"
|
||||
.format(path))
|
||||
status = git.status("-s")
|
||||
if len(status.splitlines()) > 0:
|
||||
try:
|
||||
Log.debug(self, "WOGit: git commit at {0}"
|
||||
.format(path))
|
||||
git.add("--all")
|
||||
git.commit("-am {0}".format(msg))
|
||||
except ErrorReturnCode as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to git commit at {0} "
|
||||
.format(path))
|
||||
else:
|
||||
Log.debug(self, "WOGit: Path {0} not present".format(path))
|
||||
|
||||
def checkfilestatus(self, repo, filepath):
|
||||
"""
|
||||
Checks status of file, If its tracked or untracked.
|
||||
"""
|
||||
global git
|
||||
git = git.bake("--git-dir={0}/.git".format(repo),
|
||||
"--work-tree={0}".format(repo))
|
||||
status = git.status("-s", "{0}".format(filepath))
|
||||
if len(status.splitlines()) > 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
47
wo/core/logging.py
Normal file
47
wo/core/logging.py
Normal file
@@ -0,0 +1,47 @@
|
||||
"""WordOps log module"""
|
||||
|
||||
|
||||
class Log:
|
||||
"""
|
||||
Logs messages with colors for different messages
|
||||
according to functions
|
||||
"""
|
||||
HEADER = '\033[95m'
|
||||
OKBLUE = '\033[94m'
|
||||
OKGREEN = '\033[92m'
|
||||
WARNING = '\033[93m'
|
||||
FAIL = '\033[91m'
|
||||
ENDC = '\033[0m'
|
||||
BOLD = '\033[1m'
|
||||
UNDERLINE = '\033[4m'
|
||||
|
||||
def error(self, msg, exit=True):
|
||||
"""
|
||||
Logs error into log file
|
||||
"""
|
||||
print(Log.FAIL + msg + Log.ENDC)
|
||||
self.app.log.error(Log.FAIL + msg + Log.ENDC)
|
||||
if exit:
|
||||
self.app.close(1)
|
||||
|
||||
def info(self, msg, end='\n', log=True):
|
||||
"""
|
||||
Logs info messages into log file
|
||||
"""
|
||||
|
||||
print(Log.OKBLUE + msg + Log.ENDC, end=end)
|
||||
if log:
|
||||
self.app.log.info(Log.OKBLUE + msg + Log.ENDC)
|
||||
|
||||
def warn(self, msg):
|
||||
"""
|
||||
Logs warning into log file
|
||||
"""
|
||||
print(Log.WARNING + msg + Log.ENDC)
|
||||
self.app.log.warn(Log.BOLD + msg + Log.ENDC)
|
||||
|
||||
def debug(self, msg):
|
||||
"""
|
||||
Logs debug messages into log file
|
||||
"""
|
||||
self.app.log.debug(Log.HEADER + msg + Log.ENDC)
|
||||
195
wo/core/logwatch.py
Normal file
195
wo/core/logwatch.py
Normal file
@@ -0,0 +1,195 @@
|
||||
|
||||
"""
|
||||
Real time log files watcher supporting log rotation.
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
import errno
|
||||
import stat
|
||||
from wo.core.logging import Log
|
||||
|
||||
|
||||
class LogWatcher(object):
|
||||
"""Looks for changes in all files of a directory.
|
||||
This is useful for watching log file changes in real-time.
|
||||
It also supports files rotation.
|
||||
|
||||
Example:
|
||||
|
||||
>>> def callback(filename, lines):
|
||||
... print filename, lines
|
||||
...
|
||||
>>> l = LogWatcher("/var/www/example.com/logs", callback)
|
||||
>>> l.loop()
|
||||
"""
|
||||
|
||||
def __init__(self, filelist, callback, extensions=["log"], tail_lines=0):
|
||||
"""Arguments:
|
||||
|
||||
(str) @folder:
|
||||
the folder to watch
|
||||
|
||||
(callable) @callback:
|
||||
a function which is called every time a new line in a
|
||||
file being watched is found;
|
||||
this is called with "filename" and "lines" arguments.
|
||||
|
||||
(list) @extensions:
|
||||
only watch files with these extensions
|
||||
|
||||
(int) @tail_lines:
|
||||
read last N lines from files being watched before starting
|
||||
"""
|
||||
self.files_map = {}
|
||||
self.filelist = filelist
|
||||
self.callback = callback
|
||||
# self.folder = os.path.realpath(folder)
|
||||
self.extensions = extensions
|
||||
# assert (os.path.isdir(self.folder), "%s does not exists"
|
||||
# % self.folder)
|
||||
for file in self.filelist:
|
||||
assert (os.path.isfile(file))
|
||||
assert callable(callback)
|
||||
self.update_files()
|
||||
# The first time we run the script we move all file markers at EOF.
|
||||
# In case of files created afterwards we don't do this.
|
||||
for id, file in list(iter(self.files_map.items())):
|
||||
file.seek(os.path.getsize(file.name)) # EOF
|
||||
if tail_lines:
|
||||
lines = self.tail(file.name, tail_lines)
|
||||
if lines:
|
||||
self.callback(file.name, lines)
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
def loop(self, interval=0.1, async=False):
|
||||
"""Start the loop.
|
||||
If async is True make one loop then return.
|
||||
"""
|
||||
while 1:
|
||||
self.update_files()
|
||||
for fid, file in list(iter(self.files_map.items())):
|
||||
self.readfile(file)
|
||||
if async:
|
||||
return
|
||||
time.sleep(interval)
|
||||
|
||||
def log(self, line):
|
||||
"""Log when a file is un/watched"""
|
||||
print(line)
|
||||
|
||||
# def listdir(self):
|
||||
# """List directory and filter files by extension.
|
||||
# You may want to override this to add extra logic or
|
||||
# globbling support.
|
||||
# """
|
||||
# ls = os.listdir(self.folder)
|
||||
# if self.extensions:
|
||||
# return ([x for x in ls if os.path.splitext(x)[1][1:]
|
||||
# in self.extensions])
|
||||
# else:
|
||||
# return ls
|
||||
|
||||
@staticmethod
|
||||
def tail(fname, window):
|
||||
"""Read last N lines from file fname."""
|
||||
try:
|
||||
f = open(fname, encoding='utf-8', mode='r')
|
||||
except IOError as err:
|
||||
if err.errno == errno.ENOENT:
|
||||
return []
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
BUFSIZ = 1024
|
||||
f.seek(0, os.SEEK_END)
|
||||
fsize = f.tell()
|
||||
block = -1
|
||||
data = ""
|
||||
exit = False
|
||||
while not exit:
|
||||
step = (block * BUFSIZ)
|
||||
if abs(step) >= fsize:
|
||||
f.seek(0)
|
||||
exit = True
|
||||
else:
|
||||
f.seek(step, os.SEEK_END)
|
||||
data = f.read().strip()
|
||||
if data.count('\n') >= window:
|
||||
break
|
||||
else:
|
||||
block -= 1
|
||||
return data.splitlines()[-window:]
|
||||
|
||||
def update_files(self):
|
||||
ls = []
|
||||
for name in self.filelist:
|
||||
absname = os.path.realpath(os.path.join(name))
|
||||
try:
|
||||
st = os.stat(absname)
|
||||
except EnvironmentError as err:
|
||||
if err.errno != errno.ENOENT:
|
||||
raise
|
||||
else:
|
||||
if not stat.S_ISREG(st.st_mode):
|
||||
continue
|
||||
fid = self.get_file_id(st)
|
||||
ls.append((fid, absname))
|
||||
|
||||
# check existent files
|
||||
for fid, file in list(iter(self.files_map.items())):
|
||||
# next(iter(graph.items()))
|
||||
try:
|
||||
st = os.stat(file.name)
|
||||
except EnvironmentError as err:
|
||||
if err.errno == errno.ENOENT:
|
||||
self.unwatch(file, fid)
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
if fid != self.get_file_id(st):
|
||||
# same name but different file (rotation); reload it.
|
||||
self.unwatch(file, fid)
|
||||
self.watch(file.name)
|
||||
|
||||
# add new ones
|
||||
for fid, fname in ls:
|
||||
if fid not in self.files_map:
|
||||
self.watch(fname)
|
||||
|
||||
def readfile(self, file):
|
||||
lines = file.readlines()
|
||||
if lines:
|
||||
self.callback(file.name, lines)
|
||||
|
||||
def watch(self, fname):
|
||||
try:
|
||||
file = open(fname, encoding='utf-8', mode='r')
|
||||
fid = self.get_file_id(os.stat(fname))
|
||||
except EnvironmentError as err:
|
||||
if err.errno != errno.ENOENT:
|
||||
raise
|
||||
else:
|
||||
self.log("watching logfile %s" % fname)
|
||||
self.files_map[fid] = file
|
||||
|
||||
def unwatch(self, file, fid):
|
||||
# file no longer exists; if it has been renamed
|
||||
# try to read it for the last time in case the
|
||||
# log rotator has written something in it.
|
||||
lines = self.readfile(file)
|
||||
self.log("un-watching logfile %s" % file.name)
|
||||
del self.files_map[fid]
|
||||
if lines:
|
||||
self.callback(file.name, lines)
|
||||
|
||||
@staticmethod
|
||||
def get_file_id(st):
|
||||
return "%xg%x" % (st.st_dev, st.st_ino)
|
||||
|
||||
def close(self):
|
||||
for id, file in list(iter(self.files_map.items())):
|
||||
file.close()
|
||||
self.files_map.clear()
|
||||
136
wo/core/mysql.py
Normal file
136
wo/core/mysql.py
Normal file
@@ -0,0 +1,136 @@
|
||||
"""WordOps MySQL core classes."""
|
||||
import pymysql
|
||||
from pymysql import connections, DatabaseError, Error
|
||||
import configparser
|
||||
from os.path import expanduser
|
||||
import sys
|
||||
import os
|
||||
from wo.core.logging import Log
|
||||
from wo.core.variables import WOVariables
|
||||
|
||||
|
||||
class MySQLConnectionError(Exception):
|
||||
"""Custom Exception when MySQL server Not Connected"""
|
||||
pass
|
||||
|
||||
|
||||
class StatementExcecutionError(Exception):
|
||||
"""Custom Exception when any Query Fails to execute"""
|
||||
pass
|
||||
|
||||
|
||||
class DatabaseNotExistsError(Exception):
|
||||
"""Custom Exception when Database not Exist"""
|
||||
pass
|
||||
|
||||
|
||||
class WOMysql():
|
||||
"""Method for MySQL connection"""
|
||||
|
||||
def connect(self):
|
||||
"""Makes connection with MySQL server"""
|
||||
try:
|
||||
if os.path.exists('/etc/mysql/conf.d/my.cnf'):
|
||||
connection = pymysql.connect(read_default_file='/etc/mysql/conf.d/my.cnf')
|
||||
else:
|
||||
connection = pymysql.connect(read_default_file='~/.my.cnf')
|
||||
return connection
|
||||
except ValueError as e:
|
||||
Log.debug(self, str(e))
|
||||
raise MySQLConnectionError
|
||||
except pymysql.err.InternalError as e:
|
||||
Log.debug(self, str(e))
|
||||
raise MySQLConnectionError
|
||||
|
||||
def dbConnection(self, db_name):
|
||||
try:
|
||||
if os.path.exists('/etc/mysql/conf.d/my.cnf'):
|
||||
connection = pymysql.connect(db=db_name,read_default_file='/etc/mysql/conf.d/my.cnf')
|
||||
else:
|
||||
connection = pymysql.connect(db=db_name,read_default_file='~/.my.cnf')
|
||||
|
||||
return connection
|
||||
except DatabaseError as e:
|
||||
if e.args[1] == '#42000Unknown database \'{0}\''.format(db_name):
|
||||
raise DatabaseNotExistsError
|
||||
else:
|
||||
raise MySQLConnectionError
|
||||
except pymysql.err.InternalError as e:
|
||||
Log.debug(self, str(e))
|
||||
raise MySQLConnectionError
|
||||
except Exception as e :
|
||||
Log.debug(self, "[Error]Setting up database: \'" + str(e) + "\'")
|
||||
raise MySQLConnectionError
|
||||
|
||||
def execute(self, statement, errormsg='', log=True):
|
||||
"""Get login details from /etc/mysql/conf.d/my.cnf & Execute MySQL query"""
|
||||
connection = WOMysql.connect(self)
|
||||
log and Log.debug(self, "Exceuting MySQL Statement : {0}"
|
||||
.format(statement))
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
sql = statement
|
||||
cursor.execute(sql)
|
||||
|
||||
# connection is not autocommit by default.
|
||||
# So you must commit to save your changes.
|
||||
connection.commit()
|
||||
except AttributeError as e:
|
||||
Log.debug(self, str(e))
|
||||
raise StatementExcecutionError
|
||||
except Error as e:
|
||||
Log.debug(self, str(e))
|
||||
raise StatementExcecutionError
|
||||
finally:
|
||||
connection.close()
|
||||
|
||||
def backupAll(self):
|
||||
import subprocess
|
||||
try:
|
||||
Log.info(self, "Backing up database at location: "
|
||||
"/var/wo-mysqlbackup")
|
||||
# Setup Nginx common directory
|
||||
if not os.path.exists('/var/wo-mysqlbackup'):
|
||||
Log.debug(self, 'Creating directory'
|
||||
'/var/wo-mysqlbackup')
|
||||
os.makedirs('/var/wo-mysqlbackup')
|
||||
|
||||
db = subprocess.check_output(["mysql -Bse \'show databases\'"],
|
||||
universal_newlines=True,
|
||||
shell=True).split('\n')
|
||||
for dbs in db:
|
||||
if dbs == "":
|
||||
continue
|
||||
Log.info(self, "Backing up {0} database".format(dbs))
|
||||
p1 = subprocess.Popen("mysqldump {0}"
|
||||
" --max_allowed_packet=1024M"
|
||||
" --single-transaction".format(dbs),
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, shell=True)
|
||||
p2 = subprocess.Popen("gzip -c > /var/wo-mysqlbackup/{0}{1}.s"
|
||||
"ql.gz".format(dbs, WOVariables.wo_date),
|
||||
stdin=p1.stdout,
|
||||
shell=True)
|
||||
|
||||
# Allow p1 to receive a SIGPIPE if p2 exits
|
||||
p1.stdout.close()
|
||||
output = p1.stderr.read()
|
||||
p1.wait()
|
||||
if p1.returncode == 0:
|
||||
Log.debug(self, "done")
|
||||
else:
|
||||
Log.error(self, output.decode("utf-8"))
|
||||
except Exception as e:
|
||||
Log.error(self, "Error: process exited with status %s"
|
||||
% e)
|
||||
|
||||
def check_db_exists(self, db_name):
|
||||
try:
|
||||
if WOMysql.dbConnection(self, db_name):
|
||||
return True
|
||||
except DatabaseNotExistsError as e:
|
||||
Log.debug(self, str(e))
|
||||
return False
|
||||
except MySQLConnectionError as e:
|
||||
Log.debug(self, str(e))
|
||||
return False
|
||||
44
wo/core/nginxhashbucket.py
Normal file
44
wo/core/nginxhashbucket.py
Normal file
@@ -0,0 +1,44 @@
|
||||
"""WordOps Hash Bucket Calculator"""
|
||||
from wo.core.fileutils import WOFileUtils
|
||||
import math
|
||||
import os
|
||||
import fileinput
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
|
||||
def hashbucket(self):
|
||||
# Check Nginx Hashbucket error
|
||||
sub = subprocess.Popen('nginx -t', stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, shell=True)
|
||||
output, error_output = sub.communicate()
|
||||
if 'server_names_hash_bucket_size' not in str(error_output):
|
||||
return True
|
||||
|
||||
count = 0
|
||||
# Get the list of sites-availble
|
||||
sites_list = os.listdir("/etc/nginx/sites-enabled/")
|
||||
|
||||
# Count the number of characters in site names
|
||||
for site in sites_list:
|
||||
count = sum([count, len(site)])
|
||||
|
||||
# Calculate Nginx hash bucket size
|
||||
ngx_calc = math.trunc(sum([math.log(count, 2), 2]))
|
||||
ngx_hash = math.trunc(math.pow(2, ngx_calc))
|
||||
|
||||
# Replace hashbucket in Nginx.conf file
|
||||
if WOFileUtils.grep(self, "/etc/nginx/nginx.conf",
|
||||
"server_names_hash_bucket_size"):
|
||||
for line in fileinput.FileInput("/etc/nginx/nginx.conf", inplace=1):
|
||||
if "server_names_hash_bucket_size" in line:
|
||||
print("\tserver_names_hash_bucket_size {0};".format(ngx_hash))
|
||||
else:
|
||||
print(line, end='')
|
||||
|
||||
else:
|
||||
WOFileUtils.searchreplace(self, '/etc/nginx/nginx.conf',
|
||||
"gzip_disable \"msie6\";",
|
||||
"gzip_disable \"msie6\";\n"
|
||||
"\tserver_names_hash_bucket_size {0};\n"
|
||||
.format(ngx_hash))
|
||||
33
wo/core/sendmail.py
Normal file
33
wo/core/sendmail.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import smtplib
|
||||
import os
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.base import MIMEBase
|
||||
from email.mime.text import MIMEText
|
||||
from email.utils import COMMASPACE, formatdate
|
||||
from email import encoders
|
||||
|
||||
|
||||
def WOSendMail(send_from, send_to, subject, text, files, server="localhost",
|
||||
port=587, username='', password='', isTls=True):
|
||||
msg = MIMEMultipart()
|
||||
msg['From'] = send_from
|
||||
msg['To'] = send_to
|
||||
msg['Date'] = formatdate(localtime=True)
|
||||
msg['Subject'] = subject
|
||||
|
||||
msg.attach(MIMEText(text))
|
||||
|
||||
for f in files:
|
||||
part = MIMEBase('application', "octet-stream")
|
||||
part.set_payload(open(f, "rb").read())
|
||||
encoders.encode_base64(part)
|
||||
part.add_header('Content-Disposition', 'attachment; filename="{0}"'
|
||||
.format(os.path.basename(f)))
|
||||
msg.attach(part)
|
||||
|
||||
smtp = smtplib.SMTP(server, port)
|
||||
if isTls:
|
||||
smtp.starttls()
|
||||
|
||||
smtp.sendmail(send_from, send_to, msg.as_string())
|
||||
smtp.quit()
|
||||
134
wo/core/services.py
Normal file
134
wo/core/services.py
Normal file
@@ -0,0 +1,134 @@
|
||||
"""WordOps Service Manager"""
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from subprocess import Popen
|
||||
from wo.core.logging import Log
|
||||
import pystache
|
||||
|
||||
|
||||
class WOService():
|
||||
"""Intialization for service"""
|
||||
def ___init__():
|
||||
pass
|
||||
|
||||
def start_service(self, service_name):
|
||||
"""
|
||||
start service
|
||||
Similar to `service xyz start`
|
||||
"""
|
||||
try:
|
||||
if service_name in ['nginx', 'php5-fpm']:
|
||||
service_cmd = ('{0} -t && service {0} start'
|
||||
.format(service_name))
|
||||
else:
|
||||
service_cmd = ('service {0} start'.format(service_name))
|
||||
|
||||
Log.info(self, "Start : {0:10}" .format(service_name), end='')
|
||||
retcode = subprocess.getstatusoutput(service_cmd)
|
||||
if retcode[0] == 0:
|
||||
Log.info(self, "[" + Log.ENDC + "OK" + Log.OKBLUE + "]")
|
||||
return True
|
||||
else:
|
||||
Log.debug(self, "{0}".format(retcode[1]))
|
||||
Log.info(self, "[" + Log.FAIL + "Failed" + Log.OKBLUE+"]")
|
||||
return False
|
||||
except OSError as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "\nFailed to start service {0}"
|
||||
.format(service_name))
|
||||
|
||||
def stop_service(self, service_name):
|
||||
"""
|
||||
Stop service
|
||||
Similar to `service xyz stop`
|
||||
"""
|
||||
try:
|
||||
Log.info(self, "Stop : {0:10}" .format(service_name), end='')
|
||||
retcode = subprocess.getstatusoutput('service {0} stop'
|
||||
.format(service_name))
|
||||
if retcode[0] == 0:
|
||||
Log.info(self, "[" + Log.ENDC + "OK" + Log.OKBLUE + "]")
|
||||
return True
|
||||
else:
|
||||
Log.debug(self, "{0}".format(retcode[1]))
|
||||
Log.info(self, "[" + Log.FAIL + "Failed" + Log.OKBLUE+"]")
|
||||
return False
|
||||
except OSError as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "\nFailed to stop service : {0}"
|
||||
.format(service_name))
|
||||
|
||||
def restart_service(self, service_name):
|
||||
"""
|
||||
Restart service
|
||||
Similar to `service xyz restart`
|
||||
"""
|
||||
try:
|
||||
if service_name in ['nginx', 'php5-fpm']:
|
||||
service_cmd = ('{0} -t && service {0} restart'
|
||||
.format(service_name))
|
||||
else:
|
||||
service_cmd = ('service {0} restart'.format(service_name))
|
||||
|
||||
Log.info(self, "Restart : {0:10}".format(service_name), end='')
|
||||
retcode = subprocess.getstatusoutput(service_cmd)
|
||||
if retcode[0] == 0:
|
||||
Log.info(self, "[" + Log.ENDC + "OK" + Log.OKBLUE + "]")
|
||||
return True
|
||||
else:
|
||||
Log.debug(self, "{0}".format(retcode[1]))
|
||||
Log.info(self, "[" + Log.FAIL + "Failed" + Log.OKBLUE+"]")
|
||||
return False
|
||||
except OSError as e:
|
||||
Log.debug(self, "{0} {1}".format(e.errno, e.strerror))
|
||||
Log.error(self, "\nFailed to restart service : {0}"
|
||||
.format(service_name))
|
||||
|
||||
def reload_service(self, service_name):
|
||||
"""
|
||||
Stop service
|
||||
Similar to `service xyz stop`
|
||||
"""
|
||||
try:
|
||||
if service_name in ['nginx', 'php5-fpm']:
|
||||
service_cmd = ('{0} -t && service {0} reload'
|
||||
.format(service_name))
|
||||
else:
|
||||
service_cmd = ('service {0} reload'.format(service_name))
|
||||
|
||||
Log.info(self, "Reload : {0:10}".format(service_name), end='')
|
||||
retcode = subprocess.getstatusoutput(service_cmd)
|
||||
if retcode[0] == 0:
|
||||
Log.info(self, "[" + Log.ENDC + "OK" + Log.OKBLUE + "]")
|
||||
return True
|
||||
else:
|
||||
Log.debug(self, "{0}".format(retcode[1]))
|
||||
Log.info(self, "[" + Log.FAIL + "Failed" + Log.OKBLUE+"]")
|
||||
return False
|
||||
except OSError as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "\nFailed to reload service {0}"
|
||||
.format(service_name))
|
||||
|
||||
def get_service_status(self, service_name):
|
||||
|
||||
|
||||
try:
|
||||
is_exist = subprocess.getstatusoutput('which {0}'
|
||||
.format(service_name))
|
||||
if is_exist[0] == 0 or service_name in ['php7.0-fpm', 'php5.6-fpm']:
|
||||
retcode = subprocess.getstatusoutput('service {0} status'
|
||||
.format(service_name))
|
||||
if retcode[0] == 0:
|
||||
return True
|
||||
else:
|
||||
Log.debug(self, "{0}".format(retcode[1]))
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
except OSError as e:
|
||||
Log.debug(self, "{0}{1}".format(e.errno, e.strerror))
|
||||
Log.error(self, "Unable to get services status of {0}"
|
||||
.format(service_name))
|
||||
return False
|
||||
83
wo/core/shellexec.py
Normal file
83
wo/core/shellexec.py
Normal file
@@ -0,0 +1,83 @@
|
||||
"""WordOps Shell Functions"""
|
||||
from wo.core.logging import Log
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
|
||||
class CommandExecutionError(Exception):
|
||||
"""custom Exception for command execution"""
|
||||
pass
|
||||
|
||||
|
||||
class WOShellExec():
|
||||
"""Method to run shell commands"""
|
||||
def __init__():
|
||||
pass
|
||||
|
||||
def cmd_exec(self, command, errormsg='', log=True):
|
||||
"""Run shell command from Python"""
|
||||
try:
|
||||
log and Log.debug(self, "Running command: {0}".format(command))
|
||||
|
||||
with subprocess.Popen([command], stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, shell=True) as proc:
|
||||
(cmd_stdout_bytes, cmd_stderr_bytes) = proc.communicate()
|
||||
(cmd_stdout, cmd_stderr) = (cmd_stdout_bytes.decode('utf-8',
|
||||
"replace"),
|
||||
cmd_stderr_bytes.decode('utf-8',
|
||||
"replace"))
|
||||
|
||||
if proc.returncode == 0:
|
||||
Log.debug(self, "Command Output: {0}, \nCommand Error: {1}"
|
||||
.format(cmd_stdout, cmd_stderr))
|
||||
return True
|
||||
else:
|
||||
Log.debug(self, "Command Output: {0}, \nCommand Error: {1}"
|
||||
.format(cmd_stdout, cmd_stderr))
|
||||
return False
|
||||
except OSError as e:
|
||||
Log.debug(self, str(e))
|
||||
raise CommandExecutionError
|
||||
except Exception as e:
|
||||
Log.debug(self, str(e))
|
||||
raise CommandExecutionError
|
||||
|
||||
def invoke_editor(self, filepath, errormsg=''):
|
||||
"""
|
||||
Open files using sensible editor
|
||||
"""
|
||||
try:
|
||||
subprocess.call(['sensible-editor', filepath])
|
||||
except OSError as e:
|
||||
Log.debug(self, "{0}{1}".format(e.errno, e.strerror))
|
||||
raise CommandExecutionError
|
||||
|
||||
|
||||
def cmd_exec_stdout(self, command, errormsg='', log=True):
|
||||
"""Run shell command from Python"""
|
||||
try:
|
||||
log and Log.debug(self, "Running command: {0}".format(command))
|
||||
|
||||
with subprocess.Popen([command], stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, shell=True) as proc:
|
||||
(cmd_stdout_bytes, cmd_stderr_bytes) = proc.communicate()
|
||||
(cmd_stdout, cmd_stderr) = (cmd_stdout_bytes.decode('utf-8',
|
||||
"replace"),
|
||||
cmd_stderr_bytes.decode('utf-8',
|
||||
"replace"))
|
||||
|
||||
if proc.returncode == 0:
|
||||
Log.debug(self, "Command Output: {0}, \nCommand Error: {1}"
|
||||
.format(cmd_stdout, cmd_stderr))
|
||||
return cmd_stdout
|
||||
else:
|
||||
Log.debug(self, "Command Output: {0}, \nCommand Error: {1}"
|
||||
.format(cmd_stdout, cmd_stderr))
|
||||
return cmd_stdout
|
||||
except OSError as e:
|
||||
Log.debug(self, str(e))
|
||||
raise CommandExecutionError
|
||||
except Exception as e:
|
||||
Log.debug(self, str(e))
|
||||
raise CommandExecutionError
|
||||
43
wo/core/sslutils.py
Normal file
43
wo/core/sslutils.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import os
|
||||
from wo.core.shellexec import WOShellExec
|
||||
from wo.core.logging import Log
|
||||
|
||||
|
||||
class SSL:
|
||||
|
||||
def getExpirationDays(self,domain,returnonerror=False):
|
||||
# check if exist
|
||||
if not os.path.isfile('/etc/letsencrypt/live/{0}/cert.pem'
|
||||
.format(domain)):
|
||||
Log.error(self,'File Not Found : /etc/letsencrypt/live/{0}/cert.pem'
|
||||
.format(domain),False)
|
||||
if returnonerror:
|
||||
return -1
|
||||
Log.error(self, "Check the WordOps log for more details "
|
||||
"`tail /var/log/wo/wordops.log` and please try again...")
|
||||
|
||||
|
||||
current_date = WOShellExec.cmd_exec_stdout(self, "date -d \"now\" +%s")
|
||||
expiration_date = WOShellExec.cmd_exec_stdout(self, "date -d \"`openssl x509 -in /etc/letsencrypt/live/{0}/cert.pem"
|
||||
" -text -noout|grep \"Not After\"|cut -c 25-`\" +%s".format(domain))
|
||||
|
||||
days_left = int((int(expiration_date) - int(current_date))/ 86400)
|
||||
if (days_left > 0):
|
||||
return days_left
|
||||
else:
|
||||
# return "Certificate Already Expired ! Please Renew soon."
|
||||
return -1
|
||||
|
||||
def getExpirationDate(self,domain):
|
||||
# check if exist
|
||||
if not os.path.isfile('/etc/letsencrypt/live/{0}/cert.pem'
|
||||
.format(domain)):
|
||||
Log.error(self,'File Not Found : /etc/letsencrypt/live/{0}/cert.pem'
|
||||
.format(domain),False)
|
||||
Log.error(self, "Check the WordOps log for more details "
|
||||
"`tail /var/log/wo/wordops.log` and please try again...")
|
||||
|
||||
expiration_date = WOShellExec.cmd_exec_stdout(self, "date -d \"`openssl x509 -in /etc/letsencrypt/live/{0}/cert.pem"
|
||||
" -text -noout|grep \"Not After\"|cut -c 25-`\" ".format(domain))
|
||||
return expiration_date
|
||||
|
||||
209
wo/core/variables.py
Normal file
209
wo/core/variables.py
Normal file
@@ -0,0 +1,209 @@
|
||||
"""WordOps core variable module"""
|
||||
import platform
|
||||
import socket
|
||||
import configparser
|
||||
import os
|
||||
import sys
|
||||
import psutil
|
||||
import datetime
|
||||
|
||||
|
||||
class WOVariables():
|
||||
"""Intialization of core variables"""
|
||||
|
||||
# WordOps version
|
||||
wo_version = "3.9.0"
|
||||
# WordOps packages versions
|
||||
wo_wp_cli = "2.0.1"
|
||||
wo_adminer = "4.6.3"
|
||||
|
||||
# Get WPCLI path
|
||||
wo_wpcli_path = os.popen('which wp | tr "\n" " "').read()
|
||||
if wo_wpcli_path == '':
|
||||
wo_wpcli_path = '/usr/bin/wp '
|
||||
|
||||
# Current date and time of System
|
||||
wo_date = datetime.datetime.now().strftime('%d%b%Y%H%M%S')
|
||||
|
||||
# WordOps core variables
|
||||
wo_platform_distro = platform.linux_distribution()[0].lower()
|
||||
wo_platform_version = platform.linux_distribution()[1]
|
||||
wo_platform_codename = os.popen("lsb_release -sc | tr -d \'\\n\'").read()
|
||||
|
||||
# Get timezone of system
|
||||
if os.path.isfile('/etc/timezone'):
|
||||
with open("/etc/timezone", "r") as tzfile:
|
||||
wo_timezone = tzfile.read().replace('\n', '')
|
||||
if wo_timezone == "Etc/UTC":
|
||||
wo_timezone = "UTC"
|
||||
else:
|
||||
wo_timezone = "Europe/Amsterdam"
|
||||
|
||||
# Get FQDN of system
|
||||
wo_fqdn = socket.getfqdn()
|
||||
|
||||
# WordOps default webroot path
|
||||
wo_webroot = '/var/www/'
|
||||
|
||||
# PHP5 user
|
||||
wo_php_user = 'www-data'
|
||||
|
||||
# Get git user name and EMail
|
||||
config = configparser.ConfigParser()
|
||||
config.read(os.path.expanduser("~")+'/.gitconfig')
|
||||
try:
|
||||
wo_user = config['user']['name']
|
||||
wo_email = config['user']['email']
|
||||
except Exception as e:
|
||||
wo_user = input("Enter your name: ")
|
||||
wo_email = input("Enter your email: ")
|
||||
os.system("git config --global user.name {0}".format(wo_user))
|
||||
os.system("git config --global user.email {0}".format(wo_email))
|
||||
|
||||
# Get System RAM and SWAP details
|
||||
wo_ram = psutil.virtual_memory().total / (1024 * 1024)
|
||||
wo_swap = psutil.swap_memory().total / (1024 * 1024)
|
||||
|
||||
# MySQL hostname
|
||||
wo_mysql_host = ""
|
||||
config = configparser.RawConfigParser()
|
||||
if os.path.exists('/etc/mysql/conf.d/my.cnf'):
|
||||
cnfpath = "/etc/mysql/conf.d/my.cnf"
|
||||
else:
|
||||
cnfpath = os.path.expanduser("~")+"/.my.cnf"
|
||||
if [cnfpath] == config.read(cnfpath):
|
||||
try:
|
||||
wo_mysql_host = config.get('client', 'host')
|
||||
except configparser.NoOptionError as e:
|
||||
wo_mysql_host = "localhost"
|
||||
else:
|
||||
wo_mysql_host = "localhost"
|
||||
|
||||
# WordOps stack installation variables
|
||||
# Nginx repo and packages
|
||||
if wo_platform_codename == 'precise':
|
||||
wo_nginx_repo = ("deb http://download.opensuse.org/repositories/home:"
|
||||
"/rtCamp:/EasyEngine/xUbuntu_12.04/ /")
|
||||
elif wo_platform_codename == 'trusty':
|
||||
wo_nginx_repo = ("deb http://download.opensuse.org/repositories/home:"
|
||||
"/rtCamp:/EasyEngine/xUbuntu_14.04/ /")
|
||||
elif wo_platform_codename == 'xenial':
|
||||
wo_nginx_repo = ("deb http://download.opensuse.org/repositories/home:"
|
||||
"/rtCamp:/EasyEngine/xUbuntu_16.04/ /")
|
||||
elif wo_platform_codename == 'bionic':
|
||||
wo_nginx_repo = ("deb http://download.opensuse.org/repositories/home:"
|
||||
"/rtCamp:/EasyEngine/xUbuntu_18.04/ /")
|
||||
elif wo_platform_codename == 'whwozy':
|
||||
wo_nginx_repo = ("deb http://download.opensuse.org/repositories/home:"
|
||||
"/rtCamp:/EasyEngine/Debian_7.0/ /")
|
||||
elif wo_platform_codename == 'jessie':
|
||||
wo_nginx_repo = ("deb http://download.opensuse.org/repositories/home:"
|
||||
"/rtCamp:/EasyEngine/Debian_8.0/ /")
|
||||
|
||||
|
||||
wo_nginx = ["nginx-custom", "nginx-ee"]
|
||||
wo_nginx_key = '3050AC3CD2AE6F03'
|
||||
|
||||
# PHP repo and packages
|
||||
if wo_platform_distro == 'ubuntu':
|
||||
if wo_platform_codename == 'precise':
|
||||
wo_php_repo = "ppa:ondrej/php5-5.6"
|
||||
wo_php = ["php5-fpm", "php5-curl", "php5-gd", "php5-imap",
|
||||
"php5-mcrypt", "php5-common", "php5-readline",
|
||||
"php5-mysql", "php5-cli", "php5-memcache", "php5-imagick",
|
||||
"memcached", "graphviz", "php-pear"]
|
||||
elif (wo_platform_codename == 'trusty' or wo_platform_codename == 'xenial' or wo_platform_codename == 'bionic'):
|
||||
wo_php_repo = "ppa:ondrej/php"
|
||||
# PHP5.6 for those who like to live on the dangerous side
|
||||
wo_php5_6 = ["php5.6-fpm", "php5.6-curl", "php5.6-gd", "php5.6-imap",
|
||||
"php5.6-mcrypt", "php5.6-readline", "php5.6-common", "php5.6-recode",
|
||||
"php5.6-mysql", "php5.6-cli", "php5.6-curl", "php5.6-mbstring",
|
||||
"php5.6-bcmath", "php5.6-mysql", "php5.6-opcache", "php5.6-zip", "php5.6-xml", "php5.6-soap"]
|
||||
# PHP7.0 going EOL soon
|
||||
wo_php7_0 = ["php7.0-fpm", "php7.0-curl", "php7.0-gd", "php7.0-imap",
|
||||
"php7.0-mcrypt", "php7.0-readline", "php7.0-common", "php7.0-recode",
|
||||
"php7.0-cli", "php7.0-mbstring",
|
||||
"php7.0-bcmath", "php7.0-mysql", "php7.0-opcache", "php7.0-zip", "php7.0-xml", "php7.0-soap"]
|
||||
wo_php7_2 = ["php7.2-fpm", "php7.2-curl", "php7.2-gd", "php7.2-imap",
|
||||
"php7.2-readline", "php7.2-common", "php7.2-recode",
|
||||
"php7.2-cli", "php7.2-mbstring",
|
||||
"php7.2-bcmath", "php7.2-mysql", "php7.2-opcache", "php7.2-zip", "php7.2-xml", "php7.2-soap"]
|
||||
wo_php_extra = ["php-memcached", "php-imagick", "php-memcache", "memcached",
|
||||
"graphviz", "php-pear", "php-xdebug", "php-msgpack", "php-redis"]
|
||||
elif wo_platform_distro == 'debian':
|
||||
if wo_platform_codename == 'wheezy':
|
||||
wo_php_repo = ("deb http://packages.dotdeb.org {codename}-php56 all"
|
||||
.format(codename=wo_platform_codename))
|
||||
else :
|
||||
wo_php_repo = ("deb http://packages.dotdeb.org {codename} all".format(codename=wo_platform_codename))
|
||||
|
||||
wo_php = ["php5-fpm", "php5-curl", "php5-gd", "php5-imap",
|
||||
"php5-mcrypt", "php5-common", "php5-readline",
|
||||
"php5-mysqlnd", "php5-cli", "php5-memcache", "php5-imagick",
|
||||
"memcached", "graphviz", "php-pear"]
|
||||
|
||||
wo_php7_0 = ["php7.0-fpm", "php7.0-curl", "php7.0-gd", "php7.0-imap",
|
||||
"php7.0-mcrypt", "php7.0-common", "php7.0-readline", "php7.0-redis",
|
||||
"php7.0-mysql", "php7.0-cli", "php7.0-memcache", "php7.0-imagick",
|
||||
"php7.0-mbstring", "php7.0-recode", "php7.0-bcmath", "php7.0-opcache", "php7.0-zip", "php7.0-xml",
|
||||
"php7.0-soap", "php7.0-msgpack",
|
||||
"memcached", "graphviz", "php-pear", "php7.0-xdebug"]
|
||||
wo_php_extra = []
|
||||
|
||||
if wo_platform_codename == 'wheezy':
|
||||
wo_php = wo_php + ["php5-dev"]
|
||||
|
||||
if wo_platform_codename == 'precise' or wo_platform_codename == 'jessie':
|
||||
wo_php = wo_php + ["php5-xdebug"]
|
||||
|
||||
# MySQL repo and packages
|
||||
if wo_platform_distro == 'ubuntu':
|
||||
wo_mysql_repo = ("deb [arch=amd64,i386,ppc64el] http://sfo1.mirrors.digitalocean.com/mariadb/repo/"
|
||||
"10.1/ubuntu {codename} main"
|
||||
.format(codename=wo_platform_codename))
|
||||
elif wo_platform_distro == 'debian':
|
||||
wo_mysql_repo = ("deb [arch=amd64,i386,ppc64el] http://sfo1.mirrors.digitalocean.com/mariadb/repo/"
|
||||
"10.1/debian {codename} main"
|
||||
.format(codename=wo_platform_codename))
|
||||
|
||||
wo_mysql = ["mariadb-server", "percona-toolkit"]
|
||||
|
||||
# HHVM repo details
|
||||
# 12.04 requires boot repository
|
||||
if wo_platform_distro == 'ubuntu':
|
||||
if wo_platform_codename == "precise":
|
||||
wo_boost_repo = ("ppa:mapnik/boost")
|
||||
wo_hhvm_repo = ("deb http://dl.hhvm.com/ubuntu {codename} main"
|
||||
.format(codename=wo_platform_codename))
|
||||
elif wo_platform_codename == "trusty":
|
||||
wo_hhvm_repo = ("deb http://dl.hhvm.com/ubuntu {codename} main"
|
||||
.format(codename=wo_platform_codename))
|
||||
else:
|
||||
wo_hhvm_repo = ("deb http://dl.hhvm.com/debian {codename} main"
|
||||
.format(codename=wo_platform_codename))
|
||||
|
||||
wo_hhvm = ["hhvm"]
|
||||
|
||||
# Redis repo details
|
||||
if wo_platform_distro == 'ubuntu':
|
||||
wo_redis_repo = ("ppa:chris-lea/redis-server")
|
||||
|
||||
else:
|
||||
wo_redis_repo = ("deb http://packages.dotdeb.org {codename} all"
|
||||
.format(codename=wo_platform_codename))
|
||||
|
||||
if (wo_platform_codename == 'trusty' or wo_platform_codename == 'xenial' or wo_platform_codename == 'bionic'):
|
||||
wo_redis = ['redis-server', 'php-redis']
|
||||
else:
|
||||
wo_redis = ['redis-server', 'php5-redis']
|
||||
|
||||
# Repo path
|
||||
wo_repo_file = "wo-repo.list"
|
||||
wo_repo_file_path = ("/etc/apt/sources.list.d/" + wo_repo_file)
|
||||
|
||||
# Application dabase file path
|
||||
basedir = os.path.abspath(os.path.dirname('/var/lib/wo/'))
|
||||
wo_db_uri = 'sqlite:///' + os.path.join(basedir, 'dbase.db')
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
0
wo/utils/__init__.py
Normal file
0
wo/utils/__init__.py
Normal file
15
wo/utils/test.py
Normal file
15
wo/utils/test.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""Testing utilities for WordOps"""
|
||||
from wo.cli.main import WOTestApp
|
||||
from cement.utils.test import *
|
||||
|
||||
|
||||
class WOTestCase(CementTestCase):
|
||||
app_class = WOTestApp
|
||||
|
||||
def setUp(self):
|
||||
"""Override setup actions (for every test)."""
|
||||
super(WOTestCase, self).setUp()
|
||||
|
||||
def tearDown(self):
|
||||
"""Override teardown actions (for every test)."""
|
||||
super(WOTestCase, self).tearDown()
|
||||
Reference in New Issue
Block a user