diff --git a/gvaweb/webtasks/tasks.py b/gvaweb/webtasks/tasks.py index 999c324..064f741 100644 --- a/gvaweb/webtasks/tasks.py +++ b/gvaweb/webtasks/tasks.py @@ -5,6 +5,10 @@ This module defines Celery_ tasks to manage website configurations. from __future__ import absolute_import import os +import subprocess +from tempfile import mkstemp + +from jinja2 import Environment, PackageLoader from celery import shared_task from celery.utils.log import get_task_logger @@ -20,6 +24,8 @@ LN_CMD = '/bin/ln' SERVICE_CMD = '/usr/sbin/service' INSTALL_CMD = '/usr/bin/install' +JINJAENV = Environment(loader=PackageLoader('webtasks', 'templates')) + def _build_vhost_config_path(sitename): return os.path.join(settings.GVAWEB_NGINX_SITES_AVAILABLE, sitename) @@ -39,6 +45,10 @@ def _build_document_root_path(sitename, username): settings.GVAWEB_WWWUSER_MOUNT, username, sitename, 'html') +def _get_template(templatename): + return JINJAENV.get_template(templatename) + + @shared_task def create_web_vhost_config(username, sitename, wildcard): """ @@ -53,6 +63,32 @@ def create_web_vhost_config(username, sitename, wildcard): :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() + os.close(nginxtemp) + 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: + _LOGGER.exception( + 'could not setup site configuration for %s', sitename) + raise Exception( + 'could not setup site configuration for %s' % sitename) + return True @shared_task @@ -65,6 +101,19 @@ def disable_web_vhost(sitename): :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: + _LOGGER.exception( + 'could not disable site configuration for %s', sitename) + raise Exception( + 'could not disable site configuration for %s' % sitename) + return True @shared_task @@ -78,6 +127,22 @@ def enable_web_vhost(sitename): :rtype: boolean """ + try: + subprocess.check_output([ + SUDO_CMD, LN_CMD, '-r', '-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: + _LOGGER.exception( + 'could not enable site configuration for %s', sitename) + raise Exception( + 'could not enable site configuration for %s' % sitename) + return True + @shared_task def delete_web_vhost_config(sitename): @@ -89,6 +154,16 @@ def delete_web_vhost_config(sitename): :rtype: boolean """ + try: + subprocess.check_output([ + SUDO_CMD, RM_CMD, _build_vhost_config_path(sitename)], + stderr=subprocess.STDOUT) + except subprocess.CalledProcessError: + _LOGGER.exception( + 'could not delete site configuration for %s', sitename) + raise Exception( + 'could not delete site configuration for %s' % sitename) + return True @shared_task @@ -101,6 +176,33 @@ def create_web_php_fpm_pool_config(username): :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() + os.close(fpmtemp) + 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: + _LOGGER.exception( + 'could not configure PHP FPM for %s', username) + raise Exception( + 'could not configure PHP FPM for %s' % username) + return True + @shared_task def delete_web_php_fpm_pool_config(username): @@ -112,3 +214,16 @@ def delete_web_php_fpm_pool_config(username): :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: + _LOGGER.exception( + 'could not delete PHP FPM configuration for %s', username) + raise Exception( + 'could not delete PHP FPM configuration for %s', username) + return True diff --git a/gvaweb/webtasks/templates/fpmpool.conf b/gvaweb/webtasks/templates/fpmpool.conf new file mode 100644 index 0000000..718190c --- /dev/null +++ b/gvaweb/webtasks/templates/fpmpool.conf @@ -0,0 +1,16 @@ +[{{ 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 +error_log = /var/log/php5-fpm/{{ user }}.error.log diff --git a/gvaweb/webtasks/templates/vhost.nginx b/gvaweb/webtasks/templates/vhost.nginx new file mode 100644 index 0000000..caf78ad --- /dev/null +++ b/gvaweb/webtasks/templates/vhost.nginx @@ -0,0 +1,31 @@ +server { + server_name {{ domain }}; + {%- if wildcard %} + server_name *.{{ domain|parentdomain }}; + {%- endif %} + listen 80; + listen [::] 80; + + access_log /var/log/nginx/{{ domainname }}.access.log; + error_log /var/log/nginx/{{ domainname }}.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_scriptname; + include fastcgi_params; + } + + location ~ /\.ht { + deny all; + } +} diff --git a/requirements/base.txt b/requirements/base.txt index 00c89eb..fa14272 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -5,3 +5,4 @@ billiard==3.3.0.19 celery==3.1.17 kombu==3.0.24 pytz==2014.10 +Jinja2==2.7.3