Source

fabulator / src / fabfile.py

Full commit
Benoit C 1a01758 































Benoit C 2b362d0 
Benoit C 1a01758 

Benoit C fee865f 
Benoit C 1a01758 

Benoit C 2b362d0 
Benoit C 1a01758 

Benoit C 778543d 
Benoit C b3307ed 
Benoit C 778543d 
Benoit C b3307ed 
Benoit C 778543d 
Benoit C bb01180 
Benoit C 778543d 
Benoit C b3307ed 






Benoit C 778543d 
Benoit C bb01180 
Benoit C 778543d 
Benoit C 8b39d80 
Benoit C b3307ed 

Benoit C 8b39d80 

Benoit C b3307ed 


Benoit C 8b39d80 
Benoit C 1a01758 

Benoit C bb01180 
Benoit C b3307ed 
Benoit C 1a01758 
Benoit C 8b39d80 



Benoit C 1a01758 

Benoit C 8b39d80 
Benoit C 1a01758 

Benoit C 8b39d80 
Benoit C 1a01758 
Benoit C 2b362d0 
Benoit C b3307ed 
Benoit C 1a01758 
Benoit C bb01180 
Benoit C 1a01758 
Benoit C b3307ed 
Benoit C 1a01758 







Benoit C 2b362d0 
Benoit C 1a01758 

Benoit C bb01180 
Benoit C 1a01758 
Benoit C bb01180 


Benoit C 1a01758 

Benoit C 2b362d0 
Benoit C 1a01758 

Benoit C bb01180 
Benoit C b3307ed 
Benoit C bb01180 
Benoit C b3307ed 
Benoit C bb01180 
Benoit C 1a01758 




Benoit C b3307ed 
Benoit C 1a01758 
Benoit C 2b362d0 
Benoit C b3307ed 
Benoit C 1a01758 
Benoit C bb01180 
Benoit C b3307ed 


Benoit C bb01180 

Benoit C b3307ed 
Benoit C bb01180 
Benoit C b3307ed 
Benoit C 1a01758 
Benoit C 2b362d0 


Benoit C bb01180 
Benoit C 2b362d0 

Benoit C bb01180 
Benoit C 2b362d0 




Benoit C bb01180 
Benoit C 2b362d0 
Benoit C 1a01758 

Benoit C bb01180 
Benoit C 2b362d0 
Benoit C 5155d17 
Benoit C bb01180 
Benoit C 1a01758 
Benoit C 2b362d0 
Benoit C fee865f 
Benoit C 5155d17 
Benoit C bb01180 
Benoit C 2b362d0 
Benoit C 5155d17 




Benoit C fee865f 
Benoit C 5155d17 
Benoit C 2b362d0 

Benoit C 1a01758 


Benoit C b3307ed 
Benoit C 5155d17 













Benoit C b3307ed 
Benoit C bb01180 
Benoit C b3307ed 
Benoit C 2b362d0 
Benoit C 5155d17 




Benoit C 1a01758 
Benoit C 2b362d0 
Benoit C 1a01758 

Benoit C bb01180 
Benoit C 1a01758 




Benoit C 2b362d0 
Benoit C 1a01758 

Benoit C bb01180 
Benoit C 1a01758 





Benoit C 2b362d0 
Benoit C 1a01758 

Benoit C bb01180 
Benoit C 1a01758 



Benoit C bb01180 

Benoit C 1a01758 
Benoit C 8b39d80 





















Benoit C 1a01758 

Benoit C b3307ed 




Benoit C bb01180 
Benoit C b3307ed 

Benoit C bb01180 
Benoit C 8b39d80 

Benoit C bb01180 
Benoit C 1a01758 
Benoit C 8b39d80 
Benoit C bb01180 
Benoit C 1a01758 
Benoit C 8b39d80 
Benoit C bb01180 
Benoit C 1a01758 
Benoit C 8b39d80 

Benoit C 1a01758 
# -*- coding: utf-8 -
"""
    Une documentation de ce fabfile s'impose.

    fabric est une solution de deploiment
    -> http://docs.fabfile.org/0.9.0/

    ce fichier définit des rules pour:

    -> restarter les services (nginx, gunicorn, memcached)
    -> mettre a jour le code (via mercurial)

    chaque path est configurable via le fichier conf.yaml.

    notez que:
        - c'est super dépendant du path et du repository qui sont 
        toujours organisés de la sorte chez moi:

        repos/
            src/
                <project_django>/   # le dossier du projet django
            sandbox/                # le virtualenv
            deploy/                 # le dossier ou se trouve le fabfile
            doc/                    # ce dossier est voué a etre vide

    généralement, il me suffit de faire:
    fab {pre,}prod install

    todo: 
        - ajouter south
"""
import os
import datetime
from fabric.api import *
from fabric.contrib.files import exists, sed
from fabulator.decorators import Permissions, ConfChecker

import yaml
import time


def load_yaml(env_type, conf):
    # sure we can do more there
    env.yaml = yaml.load(file(conf).read()).get(env_type)

def preprod(conf="conf.yaml"):
    """Preprod tasks"""
    load_yaml('preprod', conf)
    env.project_name = env.yaml.get('project').get('name')
    env.type = 'preprod'
    env.hosts = env.yaml.get('hosts').get('web')
    env.user = env.yaml.get('project').get('sudo_user')
    env.path = env.yaml.get('project').get('root_dir')
    env.virtualhost_path = env.path

def prod(conf="conf.yaml"):
    """Prod tasks"""
    load_yaml('prod', conf)
    env.project_name = env.yaml.get('project').get('name')
    env.type = 'prod'
    env.hosts = env.yaml.get('hosts').get('web')
    env.user = env.yaml.get('project').get('sudo_user')
    env.path = env.yaml.get('project').get('root_dir')
    env.virtualhost_path = env.path


@Permissions("normal_user", env)
@ConfChecker("wsgi", env)
def wsgi_restart():
    """Restarts the wsgi process"""
    conf = env.yaml.get("wsgi")
    django = env.yaml.get("django")
    if isinstance(conf.get('port'), list):
        for port in conf.get('port'):
            pidfile = "%s.%d" % (conf.get('pidfile'), port)
            if exists(pidfile):
                run("kill -0 `cat %s`" % pidfile)
                run("kill -HUP `head -1 %s`" % pidfile)
            else:
                run("%s/gunicorn_django --workers=%d --port=%d --pid=%s --log-file=%s -D" % \
                        (conf.get('path'), conf.get('workers'),
                         port, pidfile, conf.get('logfile')))

@Permissions("sudo_user", env)
@ConfChecker("httpd", env)
def install_httpd_vhost():
    """Install the vhost for your favorite httpd"""
    with cd(env.path):
        conf = env.yaml.get("httpd")
        fname = "%s/deploy/vhost-%s-%s" % (env.path, env.type, env.project_name)
        run("mkdir -p %s/logs/" % env.path)
        sed(fname, "DOCUMENT_ROOT", "%s" % env.path)
        sudo("cp %s %s/%s" % (fname, conf.get("av"), env.project_name))
        sudo("ln -sFf %s/%s %s" % (conf.get("av"), env.project_name, conf.get("en")))



@Permissions("normal_user", env)
@ConfChecker("django", env)
def django_settings():
    """Copies your django settings"""
    conf = env.yaml.get('django')
    with cd("%(doc_root)s" % conf):
        run("cp deploy/%s-settings.py %s/settings_local.py" % (env.type, conf.get('src_dir')))
        sed("%s/settings_local.py" % conf.get('src_dir'), "DOCUMENT_ROOT", "%s" % env.path)


@Permissions("normal_user", env)
@ConfChecker("hg", env)
def update_hg():
    """update your sources"""
    conf = env.yaml.get('hg')
    proj = env.yaml.get('project')
    if exists(conf.get('dest')):
        with cd(conf.get('dest')):
            run("hg pull -u")
            run("hg update -C")
    else:
        conf = env.yaml.get("hg")
        run("mkdir -p %s" % os.path.dirname(env.path))
        run("hg clone http://%(user)s:%(pw)s@%(url)s/%(repos)s %(dest)s" % conf)

@Permissions("normal_user", env)
@ConfChecker("virtualenv", env)
def virtualenv():
    """Create or update your virtualenv"""
    conf = env.yaml.get('virtualenv')
    deploy_dir = env.path + "/" + env.project_name + "/deploy"
    if not exists(conf.get('dir')):
        ret = run("virtualenv %(dir)s" % conf)
        print ret
        run("%(bin_dir)s/easy_install pip" % conf)

    run("%s/pip install -r %s/requirements.txt" % (conf.get('bin_dir'), deploy_dir))

@Permissions("normal_user", env)
@ConfChecker("database", env)
def backup_database():
    """Backups your mysql database"""
    conf = env.yaml.get("database")
    date = datetime.datetime.now()

    conf['backup_fname'] = "%s/backup-%s-%d-%d-%d-%s.sql" % \
        (conf.get('backup'), conf.get('db'), date.day, date.month, date.year, time.time())
    run("mkdir -p %(backup)s" % conf)
    run("""mysqldump --host=%(host)s --user=%(user)s --password=%(pw)s %(db)s > %(backup_fname)s""" % conf)


@Permissions("normal_user", env)
@ConfChecker("database", env)
def update_database():
    """Updates your database schema"""
    # first backup the database
    #backup_database()

    conf = env.yaml.get("database")
    django = env.yaml.get("django")
    venv = env.yaml.get("virtualenv")
    date = datetime.datetime.now()

    with cd(django.get("src_dir")):
        for app in django.get('apps'):
            venv["app"] = app
            run("%(bin_dir)s/python manage.py startmigration %(app)s automigration --auto" % venv)
            del venv["app"]

        run("%(bin_dir)s/python manage.py migrate --all" % venv)

        pass

    #first, create a local change in the database with south
    #apply the change

@Permissions("normal_user", env)
@ConfChecker("django", env)
def install_south():
    """Install the required tables and initialize south"""
    django = env.yaml.get("django")
    venv = env.yaml.get("virtualenv")
    with cd("%(src_dir)s" % django):
        run("%(bin_dir)s/python manage.py syncdb" % venv)
        for app in django.get('apps'):
            venv["app"] = app
            run("%(bin_dir)s/python manage.py convert_to_south %(app)s" % venv)
            del venv["app"]

@Permissions("normal_user", env)
@ConfChecker("database", env)
def install_database():
    """Install your database schema"""
    conf = env.yaml.get("database")
    django = env.yaml.get("django")
    venv = env.yaml.get("virtualenv")
    install_south()
    with cd("%(src_dir)s" % django):
        run("%(bin_dir)s/python manage.py migrate --all" % venv)


@Permissions("sudo_user", env)
@ConfChecker("services", env)
def services_reload():
    """Reloads your services"""
    services = env.yaml.get('services').get('reload')
    for service in services:
        sudo("/etc/init.d/%s reload" % service)
    print services

@Permissions("sudo_user", env)
@ConfChecker("services", env)
def services_restart():
    """Restarts your services"""
    services = env.yaml.get('services').get('restart')
    for service in services:
        sudo("/etc/init.d/%s restart" % service)
    print services


@Permissions("sudo_user", env)
@ConfChecker("distro", env)
def distro_install():
    """Installs required packages"""
    # install packages specified in the yaml conf
    dist_conf = env.yaml.get('distro')
    if dist_conf.get('name') in ('ubuntu', 'debian'):
        for package in dist_conf.get('packages'):
            sudo("apt-get install %s" % package)


def update():
    """updates the code and everything else"""
    distro_install()

    update_hg

    install_httpd_vhost()

    update_database()
    # install django configuration
    django_settings()

    # start/restart the wsgi/fcgi process
    wsgi_restart()

    # restart other services
    services_reload()
    services_restart()




def install():
    """for the first install onto the machines"""
    # install required packages 
    distro_install()

    # update the hg repos
    update_hg()

    # install the vhost required for the django application
    install_httpd_vhost()

    # install the database schema
    install_database()

    # install django configuration
    django_settings()

    # start/restart the wsgi/fcgi process
    wsgi_restart()

    # restart other services
    services_reload()
    services_restart()