Files
WPIQ/wo/cli/plugins/site.py

497 lines
20 KiB
Python
Raw Normal View History

import glob
import os
import subprocess
from cement.core.controller import CementBaseController, expose
2019-12-09 13:56:00 +01:00
from wo.cli.plugins.site_functions import (
check_domain_exists, deleteDB, deleteWebRoot, removeNginxConf, logwatch)
from wo.cli.plugins.sitedb import (deleteSiteInfo, getAllsites,
getSiteInfo, updateSiteInfo)
from wo.cli.plugins.site_create import WOSiteCreateController
from wo.cli.plugins.site_update import WOSiteUpdateController
2019-09-19 14:07:34 +02:00
from wo.core.domainvalidate import WODomain
from wo.core.fileutils import WOFileUtils
2018-11-13 21:55:59 +01:00
from wo.core.git import WOGit
2019-08-18 00:03:11 +02:00
from wo.core.logging import Log
from wo.core.services import WOService
from wo.core.shellexec import WOShellExec, CommandExecutionError
from wo.core.sslutils import SSL
2019-10-02 13:13:32 +02:00
from wo.core.variables import WOVar
from wo.core.acme import WOAcme
2018-11-13 21:55:59 +01:00
def wo_site_hook(app):
from wo.core.database import init_db
import wo.cli.plugins.models
init_db(app)
class WOSiteController(CementBaseController):
class Meta:
label = 'site'
stacked_on = 'base'
stacked_type = 'nested'
description = ('Performs website specific operations')
arguments = [
(['site_name'],
dict(help='Website name', nargs='?')),
]
2018-11-13 21:55:59 +01:00
usage = "wo site (command) <site_name> [options]"
@expose(hide=True)
def default(self):
self.app.args.print_help()
@expose(help="Enable site example.com")
def enable(self):
pargs = self.app.pargs
if not pargs.site_name:
2018-11-13 21:55:59 +01:00
try:
while not pargs.site_name:
pargs.site_name = (input('Enter site name : ')
.strip())
2018-11-13 21:55:59 +01:00
except IOError as e:
2019-07-29 04:23:37 +02:00
Log.debug(self, str(e))
2018-11-13 21:55:59 +01:00
Log.error(self, 'could not input site name')
pargs.site_name = pargs.site_name.strip()
2018-11-13 21:55:59 +01:00
# validate domain name
2019-10-02 13:13:32 +02:00
wo_domain = WODomain.validate(self, pargs.site_name)
2018-11-13 21:55:59 +01:00
# check if site exists
if not check_domain_exists(self, wo_domain):
Log.error(self, "site {0} does not exist".format(wo_domain))
if os.path.isfile('/etc/nginx/sites-available/{0}'
.format(wo_domain)):
Log.info(self, "Enable domain {0:10} \t".format(wo_domain), end='')
WOFileUtils.create_symlink(self,
['/etc/nginx/sites-available/{0}'
.format(wo_domain),
'/etc/nginx/sites-enabled/{0}'
.format(wo_domain)])
WOGit.add(self, ["/etc/nginx"],
msg="Enabled {0} "
.format(wo_domain))
updateSiteInfo(self, wo_domain, enabled=True)
Log.info(self, "[" + Log.ENDC + "OK" + Log.OKBLUE + "]")
if not WOService.reload_service(self, 'nginx'):
Log.error(self, "service nginx reload failed. "
"check issues with `nginx -t` command")
else:
Log.error(self, 'nginx configuration file does not exist')
2018-11-13 21:55:59 +01:00
@expose(help="Disable site example.com")
def disable(self):
pargs = self.app.pargs
if not pargs.site_name:
2018-11-13 21:55:59 +01:00
try:
while not pargs.site_name:
pargs.site_name = (input('Enter site name : ')
.strip())
2018-11-13 21:55:59 +01:00
except IOError as e:
2019-07-29 04:23:37 +02:00
Log.debug(self, str(e))
2018-11-13 21:55:59 +01:00
Log.error(self, 'could not input site name')
pargs.site_name = pargs.site_name.strip()
2019-10-02 13:13:32 +02:00
wo_domain = WODomain.validate(self, pargs.site_name)
2018-11-13 21:55:59 +01:00
# check if site exists
if not check_domain_exists(self, wo_domain):
Log.error(self, "site {0} does not exist".format(wo_domain))
if os.path.isfile('/etc/nginx/sites-available/{0}'
.format(wo_domain)):
Log.info(self, "Disable domain {0:10} \t"
.format(wo_domain), end='')
if not os.path.isfile('/etc/nginx/sites-enabled/{0}'
.format(wo_domain)):
Log.debug(self, "Site {0} already disabled".format(wo_domain))
Log.info(self, "[" + Log.FAIL + "Failed" + Log.OKBLUE + "]")
2018-11-13 21:55:59 +01:00
else:
WOFileUtils.remove_symlink(self,
'/etc/nginx/sites-enabled/{0}'
.format(wo_domain))
WOGit.add(self, ["/etc/nginx"],
msg="Disabled {0} "
.format(wo_domain))
updateSiteInfo(self, wo_domain, enabled=False)
Log.info(self, "[" + Log.ENDC + "OK" + Log.OKBLUE + "]")
if not WOService.reload_service(self, 'nginx'):
Log.error(self, "service nginx reload failed. "
"check issues with `nginx -t` command")
else:
2019-09-02 22:24:46 +02:00
Log.error(self, "nginx configuration file does not exist")
2018-11-13 21:55:59 +01:00
@expose(help="Get example.com information")
def info(self):
pargs = self.app.pargs
if not pargs.site_name:
2018-11-13 21:55:59 +01:00
try:
while not pargs.site_name:
pargs.site_name = (input('Enter site name : ')
.strip())
2018-11-13 21:55:59 +01:00
except IOError as e:
2019-07-29 04:23:37 +02:00
Log.debug(self, str(e))
2018-11-13 21:55:59 +01:00
Log.error(self, 'could not input site name')
pargs.site_name = pargs.site_name.strip()
2019-10-02 13:13:32 +02:00
wo_domain = WODomain.validate(self, pargs.site_name)
2019-10-01 04:08:54 +02:00
(wo_domain_type, wo_root_domain) = WODomain.getlevel(
2019-09-30 03:10:30 +02:00
self, wo_domain)
2018-11-13 21:55:59 +01:00
wo_db_name = ''
wo_db_user = ''
wo_db_pass = ''
2019-03-13 11:55:18 +01:00
2018-11-13 21:55:59 +01:00
if not check_domain_exists(self, wo_domain):
Log.error(self, "site {0} does not exist".format(wo_domain))
if os.path.isfile('/etc/nginx/sites-available/{0}'
.format(wo_domain)):
siteinfo = getSiteInfo(self, wo_domain)
sitetype = siteinfo.site_type
cachetype = siteinfo.cache_type
wo_site_webroot = siteinfo.site_path
access_log = (wo_site_webroot + '/logs/access.log')
error_log = (wo_site_webroot + '/logs/error.log')
wo_db_name = siteinfo.db_name
wo_db_user = siteinfo.db_user
wo_db_pass = siteinfo.db_password
php_version = siteinfo.php_version
ssl = ("enabled" if siteinfo.is_ssl else "disabled")
if (ssl == "enabled"):
sslprovider = "Lets Encrypt"
sslexpiry = str(SSL.getexpirationdays(self, wo_domain))
2018-11-13 21:55:59 +01:00
else:
sslprovider = ''
sslexpiry = ''
data = dict(domain=wo_domain, domain_type=wo_domain_type,
webroot=wo_site_webroot,
2018-11-13 21:55:59 +01:00
accesslog=access_log, errorlog=error_log,
2019-04-07 22:10:08 +02:00
dbname=wo_db_name, dbuser=wo_db_user,
php_version=php_version,
2019-03-13 11:55:18 +01:00
dbpass=wo_db_pass,
ssl=ssl, sslprovider=sslprovider, sslexpiry=sslexpiry,
2018-11-13 21:55:59 +01:00
type=sitetype + " " + cachetype + " ({0})"
.format("enabled" if siteinfo.is_enabled else
"disabled"))
self.app.render((data), 'siteinfo.mustache')
else:
2019-09-02 22:24:46 +02:00
Log.error(self, "nginx configuration file does not exist")
2018-11-13 21:55:59 +01:00
@expose(help="Monitor example.com logs")
def log(self):
pargs = self.app.pargs
pargs.site_name = pargs.site_name.strip()
2019-10-02 13:13:32 +02:00
wo_domain = WODomain.validate(self, pargs.site_name)
2018-11-13 21:55:59 +01:00
wo_site_webroot = getSiteInfo(self, wo_domain).site_path
if not check_domain_exists(self, wo_domain):
Log.error(self, "site {0} does not exist".format(wo_domain))
logfiles = glob.glob(wo_site_webroot + '/logs/*.log')
if logfiles:
logwatch(self, logfiles)
@expose(help="Display Nginx configuration of example.com")
def show(self):
pargs = self.app.pargs
if not pargs.site_name:
2018-11-13 21:55:59 +01:00
try:
while not pargs.site_name:
pargs.site_name = (input('Enter site name : ')
.strip())
2018-11-13 21:55:59 +01:00
except IOError as e:
2019-07-29 04:23:37 +02:00
Log.debug(self, str(e))
2018-11-13 21:55:59 +01:00
Log.error(self, 'could not input site name')
# TODO Write code for wo site edit command here
pargs.site_name = pargs.site_name.strip()
2019-10-02 13:13:32 +02:00
wo_domain = WODomain.validate(self, pargs.site_name)
2018-11-13 21:55:59 +01:00
if not check_domain_exists(self, wo_domain):
Log.error(self, "site {0} does not exist".format(wo_domain))
if os.path.isfile('/etc/nginx/sites-available/{0}'
.format(wo_domain)):
Log.info(self, "Display NGINX configuration for {0}"
.format(wo_domain))
f = open('/etc/nginx/sites-available/{0}'.format(wo_domain),
encoding='utf-8', mode='r')
text = f.read()
Log.info(self, Log.ENDC + text)
f.close()
else:
2019-10-28 09:22:04 +01:00
Log.error(self, "nginx configuration file does not exists")
2018-11-13 21:55:59 +01:00
@expose(help="Change directory to site webroot")
def cd(self):
pargs = self.app.pargs
if not pargs.site_name:
2018-11-13 21:55:59 +01:00
try:
while not pargs.site_name:
pargs.site_name = (input('Enter site name : ')
.strip())
2018-11-13 21:55:59 +01:00
except IOError as e:
2019-07-29 04:23:37 +02:00
Log.debug(self, str(e))
2018-11-13 21:55:59 +01:00
Log.error(self, 'Unable to read input, please try again')
pargs.site_name = pargs.site_name.strip()
2019-10-02 13:13:32 +02:00
wo_domain = WODomain.validate(self, pargs.site_name)
2018-11-13 21:55:59 +01:00
if not check_domain_exists(self, wo_domain):
Log.error(self, "site {0} does not exist".format(wo_domain))
wo_site_webroot = getSiteInfo(self, wo_domain).site_path
if os.path.isdir(wo_site_webroot):
WOFileUtils.chdir(self, wo_site_webroot)
2019-12-06 10:15:49 +01:00
try:
subprocess.call(['/bin/bash'])
except OSError as e:
Log.debug(self, "{0}{1}".format(e.errno, e.strerror))
else:
2018-11-13 21:55:59 +01:00
Log.error(self, "unable to change directory")
class WOSiteEditController(CementBaseController):
class Meta:
label = 'edit'
stacked_on = 'site'
stacked_type = 'nested'
description = ('Edit Nginx configuration of site')
arguments = [
(['site_name'],
dict(help='domain name for the site',
nargs='?')),
]
2018-11-13 21:55:59 +01:00
@expose(hide=True)
def default(self):
pargs = self.app.pargs
if not pargs.site_name:
2018-11-13 21:55:59 +01:00
try:
while not pargs.site_name:
pargs.site_name = (input('Enter site name : ')
.strip())
2018-11-13 21:55:59 +01:00
except IOError as e:
2019-07-29 04:23:37 +02:00
Log.debug(self, str(e))
2018-11-13 21:55:59 +01:00
Log.error(self, 'Unable to read input, Please try again')
pargs.site_name = pargs.site_name.strip()
2019-10-02 13:13:32 +02:00
wo_domain = WODomain.validate(self, pargs.site_name)
2018-11-13 21:55:59 +01:00
if not check_domain_exists(self, wo_domain):
Log.error(self, "site {0} does not exist".format(wo_domain))
if os.path.isfile('/etc/nginx/sites-available/{0}'
.format(wo_domain)):
try:
WOShellExec.invoke_editor(self, '/etc/nginx/sites-availa'
'ble/{0}'.format(wo_domain))
except CommandExecutionError as e:
2019-07-29 04:23:37 +02:00
Log.debug(self, str(e))
2018-11-13 21:55:59 +01:00
Log.error(self, "Failed invoke editor")
if (WOGit.checkfilestatus(self, "/etc/nginx",
2019-04-07 22:10:08 +02:00
'/etc/nginx/sites-available/{0}'
.format(wo_domain))):
2018-11-13 21:55:59 +01:00
WOGit.add(self, ["/etc/nginx"], msg="Edit website: {0}"
.format(wo_domain))
# Reload NGINX
if not WOService.reload_service(self, 'nginx'):
Log.error(self, "service nginx reload failed. "
"check issues with `nginx -t` command")
else:
2019-10-30 06:20:22 +01:00
Log.error(self, "nginx configuration file does not exists")
2018-11-13 21:55:59 +01:00
class WOSiteDeleteController(CementBaseController):
class Meta:
label = 'delete'
stacked_on = 'site'
stacked_type = 'nested'
description = 'delete an existing website'
arguments = [
(['site_name'],
dict(help='domain name to be deleted', nargs='?')),
(['--no-prompt'],
dict(help="doesnt ask permission for delete",
action='store_true')),
(['-f', '--force'],
2018-11-13 21:55:59 +01:00
dict(help="forcefully delete site and configuration",
action='store_true')),
(['--all'],
dict(help="delete files & db", action='store_true')),
2018-11-13 21:55:59 +01:00
(['--db'],
dict(help="delete db only", action='store_true')),
(['--files'],
dict(help="delete webroot only", action='store_true')),
]
2018-11-13 21:55:59 +01:00
@expose(help="Delete website configuration and files")
@expose(hide=True)
def default(self):
pargs = self.app.pargs
if not pargs.site_name and not pargs.all:
2018-11-13 21:55:59 +01:00
try:
while not pargs.site_name:
pargs.site_name = (input('Enter site name : ')
.strip())
2018-11-13 21:55:59 +01:00
except IOError as e:
2019-08-30 20:33:33 +02:00
Log.debug(self, str(e))
2018-11-13 21:55:59 +01:00
Log.error(self, 'could not input site name')
pargs.site_name = pargs.site_name.strip()
2019-10-02 13:13:32 +02:00
wo_domain = WODomain.validate(self, pargs.site_name)
2018-11-13 21:55:59 +01:00
wo_db_name = ''
wo_prompt = ''
wo_nginx_prompt = ''
mark_db_delete_prompt = False
mark_webroot_delete_prompt = False
mark_db_deleted = False
mark_webroot_deleted = False
if not check_domain_exists(self, wo_domain):
Log.error(self, "site {0} does not exist".format(wo_domain))
if ((not pargs.db) and (not pargs.files) and
(not pargs.all)):
pargs.all = True
2018-11-13 21:55:59 +01:00
if pargs.force:
pargs.no_prompt = True
2018-11-13 21:55:59 +01:00
# Gather information from wo-db for wo_domain
check_site = getSiteInfo(self, wo_domain)
wo_site_type = check_site.site_type
wo_site_webroot = check_site.site_path
if wo_site_webroot == 'deleted':
mark_webroot_deleted = True
if wo_site_type in ['mysql', 'wp', 'wpsubdir', 'wpsubdomain']:
wo_db_name = check_site.db_name
wo_db_user = check_site.db_user
if self.app.config.has_section('mysql'):
wo_mysql_grant_host = self.app.config.get(
'mysql', 'grant-host')
else:
wo_mysql_grant_host = 'localhost'
2018-11-13 21:55:59 +01:00
if wo_db_name == 'deleted':
mark_db_deleted = True
if pargs.all:
pargs.db = True
pargs.files = True
2018-11-13 21:55:59 +01:00
else:
if pargs.all:
2018-11-13 21:55:59 +01:00
mark_db_deleted = True
pargs.files = True
2018-11-13 21:55:59 +01:00
# Delete website database
if pargs.db:
2018-11-13 21:55:59 +01:00
if wo_db_name != 'deleted' and wo_db_name != '':
if not pargs.no_prompt:
2018-11-13 21:55:59 +01:00
wo_db_prompt = input('Are you sure, you want to delete'
' database [y/N]: ')
else:
wo_db_prompt = 'Y'
mark_db_delete_prompt = True
if wo_db_prompt == 'Y' or wo_db_prompt == 'y':
mark_db_delete_prompt = True
Log.info(self, "Deleting Database, {0}, user {1}"
.format(wo_db_name, wo_db_user))
deleteDB(self, wo_db_name, wo_db_user,
wo_mysql_grant_host, False)
2018-11-13 21:55:59 +01:00
updateSiteInfo(self, wo_domain,
db_name='deleted',
db_user='deleted',
db_password='deleted')
mark_db_deleted = True
Log.info(self, "Deleted Database successfully.")
else:
mark_db_deleted = True
Log.info(self, "Does not seems to have database for this site."
)
# Delete webroot
if pargs.files:
2018-11-13 21:55:59 +01:00
if wo_site_webroot != 'deleted':
if not pargs.no_prompt:
2018-11-13 21:55:59 +01:00
wo_web_prompt = input('Are you sure, you want to delete '
'webroot [y/N]: ')
else:
wo_web_prompt = 'Y'
mark_webroot_delete_prompt = True
if wo_web_prompt == 'Y' or wo_web_prompt == 'y':
mark_webroot_delete_prompt = True
Log.info(self, "Deleting Webroot, {0}"
.format(wo_site_webroot))
deleteWebRoot(self, wo_site_webroot)
updateSiteInfo(self, wo_domain, webroot='deleted')
mark_webroot_deleted = True
Log.info(self, "Deleted webroot successfully")
else:
mark_webroot_deleted = True
Log.info(self, "Webroot seems to be already deleted")
if not pargs.force:
2018-11-13 21:55:59 +01:00
if (mark_webroot_deleted and mark_db_deleted):
# TODO Delete nginx conf
removeNginxConf(self, wo_domain)
deleteSiteInfo(self, wo_domain)
WOAcme.removeconf(self, wo_domain)
2018-11-13 21:55:59 +01:00
Log.info(self, "Deleted site {0}".format(wo_domain))
# else:
2019-04-07 22:10:08 +02:00
# Log.error(self, " site {0} does
# not exists".format(wo_domain))
2018-11-13 21:55:59 +01:00
else:
2019-04-07 22:10:08 +02:00
if (mark_db_delete_prompt or mark_webroot_delete_prompt or
(mark_webroot_deleted and mark_db_deleted)):
2018-11-13 21:55:59 +01:00
# TODO Delete nginx conf
removeNginxConf(self, wo_domain)
deleteSiteInfo(self, wo_domain)
2020-10-26 14:21:04 +01:00
# To improve
if not WOFileUtils.grepcheck(
self, '/var/www/22222/conf/nginx/ssl.conf', wo_domain):
WOAcme.removeconf(self, wo_domain)
2018-11-13 21:55:59 +01:00
Log.info(self, "Deleted site {0}".format(wo_domain))
class WOSiteListController(CementBaseController):
class Meta:
label = 'list'
stacked_on = 'site'
stacked_type = 'nested'
description = 'List websites'
arguments = [
(['--enabled'],
dict(help='List enabled websites', action='store_true')),
(['--disabled'],
dict(help="List disabled websites", action='store_true')),
]
2018-11-13 21:55:59 +01:00
@expose(help="Lists websites")
def default(self):
pargs = self.app.pargs
sites = getAllsites(self)
if not sites:
pass
2018-11-13 21:55:59 +01:00
if pargs.enabled:
for site in sites:
if site.is_enabled:
Log.info(self, "{0}".format(site.sitename))
elif pargs.disabled:
for site in sites:
if not site.is_enabled:
Log.info(self, "{0}".format(site.sitename))
else:
for site in sites:
Log.info(self, "{0}".format(site.sitename))
2018-11-13 21:55:59 +01:00
def load(app):
# register the plugin class.. this only happens if the plugin is enabled
2019-09-24 00:01:20 +02:00
app.handler.register(WOSiteController)
app.handler.register(WOSiteDeleteController)
app.handler.register(WOSiteUpdateController)
app.handler.register(WOSiteCreateController)
2019-09-24 00:01:20 +02:00
app.handler.register(WOSiteListController)
app.handler.register(WOSiteEditController)
2018-11-13 21:55:59 +01:00
# register a hook (function) to run after arguments are parsed.
2019-09-24 00:04:32 +02:00
app.hook.register('post_argument_parsing', wo_site_hook)