Refactored
This commit is contained in:
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
|
||||
Reference in New Issue
Block a user