django-fab-deploy / fab_deploy /

The default branch has multiple heads

from __future__ import with_statement
import re
from fabric.api import *
from fabric.contrib import files

from fab_deploy import utils
from fab_deploy import system

__all__ = ['touch', 'apache_restart']

APACHE_PORTS_FILE = '/etc/apache2/ports.conf'
APACHE_FIRST_PORT = 50000 # see

def touch(wsgi_file=None):
    """ Reloads source code by touching the wsgi file. """
    if wsgi_file is None:
        wsgi_file = env.conf['ENV_DIR'] + '/var/wsgi/' + env.conf['INSTANCE_NAME'] + '.py'
    run('touch ' + wsgi_file)

def apache_make_wsgi():
    """ Uploads wsgi deployment script. """
    wsgi_dir = env.conf['ENV_DIR'] + '/var/wsgi/'
    run('mkdir -p ' + wsgi_dir)
    file_name = env.conf['INSTANCE_NAME'] + '.py'
    utils.upload_config_template('', wsgi_dir + file_name)

def apache_restart():
    """ Restarts apache using init.d script. """
    # restart is not used because it can leak memory in some cases
    sudo('invoke-rc.d apache2 stop')
    sudo('invoke-rc.d apache2 start')

# ==== installation ===

def apache_install():
    """ Installs apache. """
    system.aptitude_install('apache2 libapache2-mod-wsgi libapache2-mod-rpaf')
    sudo('rm -f /etc/apache2/sites-enabled/default')
    sudo('rm -f /etc/apache2/sites-enabled/000-default')

def apache_make_config():
    """ Updates apache config. """
    name = env.conf['INSTANCE_NAME']
                                 '/etc/apache2/sites-available/%s' % name,
    sudo('a2ensite %s' % name)

def apache_setup():
    """ Updates apache config, wsgi script and restarts apache. """

def apache_setup_locale():
    """ Setups apache locale. Apache is unable to handle file uploads with
    unicode file names without this. """
                 ['export LANG="en_US.UTF-8"', 'export LC_ALL="en_US.UTF-8"'],

# === automatic apache ports management ===

def _ports_lines():
    with settings(hide('stdout')):
        ports_data = sudo('cat ' + APACHE_PORTS_FILE)
    return ports_data.splitlines()

def _used_ports(lines):
    ports_mapping = dict()

    listen_re = re.compile('^Listen (?P<host>.+):\s*(?P<port>\d+)')
    instance_re = re.compile('^# used by (?P<instance>.+)')

    for index, line in enumerate(lines):
        match = re.match(listen_re, line)
        if match:
            instance = None
            if index:
                instance_match = re.match(instance_re, lines[index - 1])
                if instance_match:
                    instance ='instance')
            ports_mapping['port')] = instance
    return ports_mapping

def _apache_setup_port():
    Makes sure some port is correctly listened in
    :file:`ports.conf` and sets :attr:`env.conf.APACHE_PORT`
    to this port.
    lines = _ports_lines()

    # take over ports.conf
    TAKEOVER_STRING = '# This file is managed by django-fab-deploy. Please do not edit it manually.'
    if lines[0] != TAKEOVER_STRING:
        lines = [TAKEOVER_STRING]

    used_ports = _used_ports(lines)

    for port in used_ports:
        if used_ports[port] == env.conf.INSTANCE_NAME:
            # instance is binded to port
            env.conf.APACHE_PORT = port
            puts('Instance is binded to port ' + str(port))

    # instance is not binded to any port yet;
    # find an empty port and listen to it.
    for port in range(APACHE_FIRST_PORT, APACHE_LAST_PORT):
        if str(port) not in used_ports: # port is found!
                '# used by ' + env.conf.INSTANCE_NAME,
                'Listen' + str(port)
            env.conf.APACHE_PORT = port
            puts('Instance is not binded to any port. Binding it to port ' + str(port))
            sudo("echo '%s\n' > %s" % ('\n'.join(lines), APACHE_PORTS_FILE))
    warn('All apache ports are used!')