Merge branch 'release/0.1.0' into production

* release/0.1.0:
  add release version in changelog, update conf.py
  unify exception handling, fix nginx template
  fix listen directive
  wheezy's /bin/ln does not support '-r' parameter
  implement Jinja filter to calculate the parent domain of a domain
  remove pool error_log directive which is only allowed globally
  don't try to close tempfiles twice
  first tasks implementation, added nginx and FPM templates
  add wildcard support to create_web_vhost_config task
This commit is contained in:
Jan Dittberner 2015-01-27 15:30:36 +01:00
commit 1494c2ce8a
6 changed files with 168 additions and 3 deletions

View file

@ -1,4 +1,9 @@
Changelog Changelog
========= =========
* :release:`0.1.0 <2015-01-27>`
* :feature:`-` add tasks to setup and delete per user PHP5 FPM pool
configurations
* :feature:`-` add tasks to setup, enable, disable and delete nginx virtual
host configurations
* :support:`-` initial project setup * :support:`-` initial project setup

View file

@ -60,9 +60,9 @@ copyright = u'2015, Jan Dittberner'
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '0.0' version = '0.1'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.0.0' release = '0.1.0'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View file

@ -5,6 +5,10 @@ This module defines Celery_ tasks to manage website configurations.
from __future__ import absolute_import from __future__ import absolute_import
import os import os
import subprocess
from tempfile import mkstemp
from jinja2 import Environment, PackageLoader
from celery import shared_task from celery import shared_task
from celery.utils.log import get_task_logger from celery.utils.log import get_task_logger
@ -20,6 +24,21 @@ LN_CMD = '/bin/ln'
SERVICE_CMD = '/usr/sbin/service' SERVICE_CMD = '/usr/sbin/service'
INSTALL_CMD = '/usr/bin/install' INSTALL_CMD = '/usr/bin/install'
JINJAENV = Environment(loader=PackageLoader('webtasks', 'templates'))
def _jinja_parentdomain(domain):
return '.'.join(domain.split('.')[1:])
JINJAENV.filters['parentdomain'] = _jinja_parentdomain
def log_and_raise(exception, message, *args):
logargs = list(args) + [exception.returncode, exception.output]
_LOGGER.error(message + "\nreturncode: %d\noutput:\n%s", *logargs)
raise Exception(message % args)
def _build_vhost_config_path(sitename): def _build_vhost_config_path(sitename):
return os.path.join(settings.GVAWEB_NGINX_SITES_AVAILABLE, sitename) return os.path.join(settings.GVAWEB_NGINX_SITES_AVAILABLE, sitename)
@ -39,18 +58,47 @@ def _build_document_root_path(sitename, username):
settings.GVAWEB_WWWUSER_MOUNT, username, sitename, 'html') settings.GVAWEB_WWWUSER_MOUNT, username, sitename, 'html')
def _get_template(templatename):
return JINJAENV.get_template(templatename)
@shared_task @shared_task
def create_web_vhost_config(username, sitename): def create_web_vhost_config(username, sitename, wildcard):
""" """
This task creates a virtual host configuration on an nginx web This task creates a virtual host configuration on an nginx web
server. server.
:param str username: user who owns the site :param str username: user who owns the site
:param str sitename: site name :param str sitename: site name
:param boolean wildcard: designates whether this is website has a wildcard
subdomain
:return: :py:const:`True` if the creation finished successfully :return: :py:const:`True` if the creation finished successfully
:rtype: boolean :rtype: boolean
""" """
conftmpl = _get_template('vhost.nginx')
confdata = conftmpl.render(
domain=sitename, user=username,
docroot=_build_document_root_path(sitename, username),
wildcard=wildcard)
try:
nginxtemp, filename = mkstemp()
conffile = os.fdopen(nginxtemp, 'w')
conffile.write(confdata.encode('utf8'))
finally:
if conffile:
conffile.close()
try:
subprocess.check_output([
SUDO_CMD, INSTALL_CMD, '-o', 'root', '-g', 'root', '-m', '0640',
filename, _build_vhost_config_path(sitename)],
stderr=subprocess.STDOUT)
subprocess.check_output([
SUDO_CMD, RM_CMD, filename], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as cpe:
log_and_raise(
cpe, 'could not setup site configuration for %s', sitename)
return True
@shared_task @shared_task
@ -63,6 +111,17 @@ def disable_web_vhost(sitename):
:rtype: boolean :rtype: boolean
""" """
try:
subprocess.check_output([
SUDO_CMD, RM_CMD, _build_enabled_vhost_path(sitename)],
stderr=subprocess.STDOUT)
subprocess.check_output([
SUDO_CMD, SERVICE_CMD, 'nginx', 'reload'],
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as cpe:
log_and_raise(
cpe, 'could not disable site configuration for %s', sitename)
return True
@shared_task @shared_task
@ -76,6 +135,20 @@ def enable_web_vhost(sitename):
:rtype: boolean :rtype: boolean
""" """
try:
subprocess.check_output([
SUDO_CMD, LN_CMD, '-s',
_build_vhost_config_path(sitename),
_build_enabled_vhost_path(sitename)],
stderr=subprocess.STDOUT)
subprocess.check_output([
SUDO_CMD, SERVICE_CMD, 'nginx', 'restart'],
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as cpe:
log_and_raise(
cpe, 'could not enable site configuration for %s', sitename)
return True
@shared_task @shared_task
def delete_web_vhost_config(sitename): def delete_web_vhost_config(sitename):
@ -87,6 +160,14 @@ def delete_web_vhost_config(sitename):
:rtype: boolean :rtype: boolean
""" """
try:
subprocess.check_output([
SUDO_CMD, RM_CMD, _build_vhost_config_path(sitename)],
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as cpe:
log_and_raise(
cpe, 'could not delete site configuration for %s', sitename)
return True
@shared_task @shared_task
@ -99,6 +180,29 @@ def create_web_php_fpm_pool_config(username):
:rtype: boolean :rtype: boolean
""" """
conftmpl = _get_template('fpmpool.conf')
confdata = conftmpl.render(user=username)
try:
fpmtemp, filename = mkstemp()
conffile = os.fdopen(fpmtemp, 'w')
conffile.write(confdata.encode('utf8'))
finally:
if conffile:
conffile.close()
try:
subprocess.check_output([
SUDO_CMD, INSTALL_CMD, '-o', 'root', '-g', 'root', '-m', '0644',
filename, _build_php_fpm_pool_file(username)],
stderr=subprocess.STDOUT)
subprocess.check_output([
SUDO_CMD, RM_CMD, filename], stderr=subprocess.STDOUT)
subprocess.check_output([
SUDO_CMD, SERVICE_CMD, 'php5-fpm', 'reload'],
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as cpe:
log_and_raise(cpe, 'could not configure PHP FPM for %s', username)
return True
@shared_task @shared_task
def delete_web_php_fpm_pool_config(username): def delete_web_php_fpm_pool_config(username):
@ -110,3 +214,14 @@ def delete_web_php_fpm_pool_config(username):
:rtype: boolean :rtype: boolean
""" """
try:
subprocess.check_output([
SUDO_CMD, RM_CMD, _build_php_fpm_pool_file(username)],
stderr=subprocess.STDOUT)
subprocess.check_output([
SUDO_CMD, SERVICE_CMD, 'php5-fpm', 'reload'],
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as cpe:
log_and_raise(
cpe, 'could not delete PHP FPM configuration for %s', username)
return True

View file

@ -0,0 +1,15 @@
[{{ user }}]
user = {{ user }}
group = {{ user }}
listen = /var/run/php5-fpm-{{ user }}.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_requests = 1000
chdir = /
request_slowlog_timeout = 10s
slowlog = /var/log/php5-fpm/{{ user }}.slow.log

View file

@ -0,0 +1,29 @@
server {
server_name {{ domain }};
{%- if wildcard %}
server_name *.{{ domain|parentdomain }};
{%- endif %}
access_log /var/log/nginx/{{ domain }}.access.log;
error_log /var/log/nginx/{{ domain }}.error.log;
client_max_body_size 20M;
gzip on;
gzip_types text/javascript application/x-javascript text/css;
root {{ docroot }};
index index.php index.html index.htm;
location ~ ^/(.+\.php)$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php5-fpm-{{ user }}.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}

View file

@ -5,3 +5,4 @@ billiard==3.3.0.19
celery==3.1.17 celery==3.1.17
kombu==3.0.24 kombu==3.0.24
pytz==2014.10 pytz==2014.10
Jinja2==2.7.3