<file_sep>import os

import celery
import raven

from raven.contrib.celery import register_signal, register_logger_signal

from django.conf import settings  # noqa
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'falstartexample.settings')

class Celery(celery.Celery):

    """ Configure celery with raven """

    def on_configure(self):
        if not getattr(settings, 'CELERY_RAVEN_DSN'):
            # for no send raven reports from dev server
            return
        client = raven.Client(settings.CELERY_RAVEN_DSN)
        # register a custom filter to filter out duplicate logs
        register_logger_signal(client)
        # hook into the Celery error handler
        register_signal(client)


app = Celery('falstartexample')

# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
<file_sep># falstart-example
Example of the [falstart](https://github.com/Samael500/falstart)-utility result to create a basic project in Django

![falstart example](example.gif)

```Shell
$ falstart falstart-example
> Django version ['1.9.5'] 1.10.2
> Debian version (for vagrant box) ['jessie64']
> Python version ['3.5.1'] 3.5.2
> Vagrant box IP-addr ['10.1.1.123'] 10.1.1.111
> Do you nead a POSTGRES? [Y/n]
> Do you nead a CELERY? [y/N] y
> Do you nead a REDIS? [y/N] y
> Do you nead a SENTRY? [y/N] y
> Database name ['falstartexample_db']
> Database user ['falstartexample_user']
> Database pass ['<PASSWORD>']
[falstart] > make dir: "/home/maks/temp/falstart-example"
[falstart] > render "Vagrantfile.j2" > "Vagrantfile"
[falstart] > render "Makefile.j2" > "Makefile"
[falstart] > run: "chmod +x Makefile"
[falstart] > make dir: "provision"
[falstart] > make dir: "provision"
[falstart] > render "provision_fabfile.j2" > "provision/fabric_provisioner.py"
[falstart] > render "requirements.j2" > "requirements.txt"
[falstart] > render "requirements.j2" > "requirements-remote.txt"
[falstart] > render "lintrc.j2" > ".lintrc"
[falstart] > render "coveragerc.j2" > ".coveragerc"
[falstart] > make dir: "falstartexample"
[falstart] > render "py_codes/settings_local.j2" > "falstartexample/settings_local.py.example"
[falstart] > make dir: "falstartexample"
[falstart] > render "py_codes/celery.j2" > "falstartexample/celery.py"
[falstart] > copy: "/home/maks/s50/falstart/falstart/templates/vagrant_templates" > "provision/templates"
[falstart] > run: "vagrant up"
Bringing machine 'falstartexample_vagrant' up with 'virtualbox' provider...
==> falstartexample_vagrant: Checking if box 'debian/jessie64' is up to date...
==> falstartexample_vagrant: A newer version of the box 'debian/jessie64' is available! You currently
==> falstartexample_vagrant: have version '8.4.0'. The latest is version '8.6.1'. Run
==> falstartexample_vagrant: `vagrant box update` to update.
==> falstartexample_vagrant: Clearing any previously set forwarded ports...
==> falstartexample_vagrant: Fixed port collision for 22 => 2222. Now on port 2200.
==> falstartexample_vagrant: Clearing any previously set network interfaces...
==> falstartexample_vagrant: Preparing network interfaces based on configuration...
    falstartexample_vagrant: Adapter 1: nat
    falstartexample_vagrant: Adapter 2: hostonly
==> falstartexample_vagrant: Forwarding ports...
    falstartexample_vagrant: 22 (guest) => 2200 (host) (adapter 1)
==> falstartexample_vagrant: Running 'pre-boot' VM customizations...
==> falstartexample_vagrant: Booting VM...
==> falstartexample_vagrant: Waiting for machine to boot. This may take a few minutes...
    falstartexample_vagrant: SSH address: 127.0.0.1:2200
    falstartexample_vagrant: SSH username: vagrant
    falstartexample_vagrant: SSH auth method: private key
==> falstartexample_vagrant: Machine booted and ready!
==> falstartexample_vagrant: Checking for guest additions in VM...
    falstartexample_vagrant: No guest additions were detected on the base box for this VM! Guest
    falstartexample_vagrant: additions are required for forwarded ports, shared folders, host only
    falstartexample_vagrant: networking, and more. If SSH fails on this machine, please install
    falstartexample_vagrant: the guest additions and repackage the box to continue.
    falstartexample_vagrant:
    falstartexample_vagrant: This is not an error message; everything may continue to work properly,
    falstartexample_vagrant: in which case you may ignore this message.
==> falstartexample_vagrant: Setting hostname...
==> falstartexample_vagrant: Configuring and enabling network interfaces...
==> falstartexample_vagrant: Exporting NFS shared folders...
==> falstartexample_vagrant: Preparing to edit /etc/exports. Administrator privileges will be required...
[sudo] пароль для maks:
● nfs-server.service - NFS server and services
   Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled; vendor preset: enabled)
   Active: active (exited) since Вс 2016-10-09 14:40:14 MSK; 4min 16s ago
  Process: 1081 ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS (code=exited, status=0/SUCCESS)
  Process: 1073 ExecStartPre=/usr/sbin/exportfs -r (code=exited, status=0/SUCCESS)
 Main PID: 1081 (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/nfs-server.service

окт 09 14:40:13 zlm systemd[1]: Starting NFS server and services...
окт 09 14:40:14 zlm systemd[1]: Started NFS server and services.
==> falstartexample_vagrant: Mounting NFS shared folders...
==> falstartexample_vagrant: Running provisioner: fabric...
[127.0.0.1] Executing task 'common'
[127.0.0.1] put: <file obj> -> /etc/environment
[127.0.0.1] sudo: localedef ru_RU.UTF-8 -i ru_RU -fUTF-8
[127.0.0.1] sudo: touch /usr/locale_8913242974480500368
[127.0.0.1] sudo: apt-get -y update
[127.0.0.1] sudo: apt-get -y install libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev git redis-server
[127.0.0.1] sudo: touch /usr/apt_packages_-3330926058430280198
[127.0.0.1] sudo: apt-get -y install python-dev python-pip python-virtualenv build-essential libncurses5-dev libncursesw5-dev libreadline6-dev libgdbm-dev libsqlite3-dev libssl-dev libbz2-dev libexpat1-dev liblzma-dev zlib1g-dev libxml2-dev libxslt1-dev
[127.0.0.1] run: wget -O python.tgz https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tgz
[127.0.0.1] run: tar -xf python.tgz
[127.0.0.1] run: mv Python-3.5.2 python
[127.0.0.1] run: ./configure --prefix=/usr/local/python-3.5.2
[127.0.0.1] run: make
[127.0.0.1] sudo: make altinstall
[127.0.0.1] sudo: rm /tmp/* -rf
[127.0.0.1] sudo: ln -sf /usr/local/python-3.5.2/bin/* /usr/local/bin/
[127.0.0.1] sudo: touch /usr/python_packages_-535002765752534493
[127.0.0.1] Executing task 'database'
[127.0.0.1] sudo: apt-get -y install postgresql postgresql-server-dev-all python-psycopg2
[127.0.0.1] run: sudo -u postgres psql -c "CREATE USER falstartexample_user;"
[127.0.0.1] run: sudo -u postgres psql -c "ALTER USER falstartexample_user WITH PASSWORD '<PASSWORD>';"
[127.0.0.1] run: sudo -u postgres psql -c "ALTER USER falstartexample_user CREATEDB;"
[127.0.0.1] run: sudo -u postgres psql -c "CREATE DATABASE falstartexample;"
[127.0.0.1] run: sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE falstartexample TO falstartexample_user;"
[127.0.0.1] sudo: touch /usr/database_-8337542331712744645
[127.0.0.1] Executing task 'nginx'
[127.0.0.1] sudo: apt-get -y install nginx
[127.0.0.1] sudo: touch /usr/nginx_install_1687306290436383039
[127.0.0.1] put: <file obj> -> /etc/nginx/sites-available/falstartexample
[127.0.0.1] sudo: ln -sf /etc/nginx/sites-available/falstartexample /etc/nginx/sites-enabled/falstartexample
[127.0.0.1] sudo: service nginx restart
[127.0.0.1] Executing task 'app'
[127.0.0.1] run: pyvenv-3.5 /home/vagrant/venv
[127.0.0.1] run: /home/vagrant/venv/bin/pip install -U pip wheel
[127.0.0.1] run: mkdir -p wheels
[127.0.0.1] run: /home/vagrant/venv/bin/pip wheel -w wheels/ -r requirements-remote.txt --pre
[127.0.0.1] run: make wheel_install
[127.0.0.1] run: /home/vagrant/venv/bin/django-admin startproject falstartexample .
[127.0.0.1] run: cd falstartexample && cp settings_local.py.example settings_local.py
[127.0.0.1] Executing task 'localserver'
[127.0.0.1] run: /home/vagrant/venv/bin/python manage.py migrate --noinput
[127.0.0.1] run: /home/vagrant/venv/bin/python manage.py collectstatic --noinput
[127.0.0.1] run: echo "from django.contrib.auth import get_user_model
User = get_user_model()
User.objects.create_superuser(**{'username': 'root', 'password': '<PASSWORD>', 'email': '<EMAIL>@e.co'})
" | /home/vagrant/venv/bin/python manage.py shell
[127.0.0.1] run: mkdir var -p
[127.0.0.1] run: make start
[127.0.0.1] run: make runcelery_multi

Done.
Disconnecting from 127.0.0.1:2200... done.

==> falstartexample_vagrant: Machine 'falstartexample_vagrant' has a post `vagrant up` message. This is a message
==> falstartexample_vagrant: from the creator of the Vagrantfile, and not from Vagrant itself:
==> falstartexample_vagrant:
==> falstartexample_vagrant: falstartexample dev server successfuly started.
==> falstartexample_vagrant:     Connect to host with:
==> falstartexample_vagrant:     http://10.1.1.111/
==> falstartexample_vagrant:     or over ssh with `vagrant ssh`
==> falstartexample_vagrant:
==> falstartexample_vagrant:     Admin user credentials:
==> falstartexample_vagrant:       login: root
==> falstartexample_vagrant:       password: <PASSWORD>
==> falstartexample_vagrant:
[falstart] > make dir: "provision"
[falstart] > render "provision_fabfile.j2" > "provision/fabric_provisioner.py"
[falstart] > render "gitignore.j2" > ".gitignore"
[falstart] > Update .gitignore
[falstart] > run: "git add . && git commit -m ":rocket: falstart init commit""
[master 0b93d53] :rocket: falstart init commit
 39 files changed, 690 insertions(+), 4 deletions(-)
 create mode 100644 .coveragerc
 create mode 100644 .falstart.json
 create mode 100644 .lintrc
 create mode 100755 Makefile
 create mode 100644 Vagrantfile
 create mode 100644 falstartexample/__init__.py
 create mode 100644 falstartexample/celery.py
 create mode 100644 falstartexample/settings.py
 create mode 100644 falstartexample/settings_local.py.example
 create mode 100644 falstartexample/urls.py
 create mode 100644 falstartexample/wsgi.py
 create mode 100755 manage.py
 create mode 100644 provision/fabric_provisioner.py
 create mode 100644 provision/templates/environment.j2
 create mode 100644 provision/templates/locale.gen.j2
 create mode 100644 provision/templates/nginx-host.j2
 create mode 100644 requirements-remote.txt
 create mode 100644 requirements.txt
 create mode 100644 wheels/Django-1.10.2-py2.py3-none-any.whl
 create mode 100644 wheels/amqp-1.4.9-py2.py3-none-any.whl
 create mode 100644 wheels/anyjson-0.3.3-py3-none-any.whl
 create mode 100644 wheels/billiard-3.3.0.23-py3-none-any.whl
 create mode 100644 wheels/celery-3.1.23-py2.py3-none-any.whl
 create mode 100644 wheels/contextlib2-0.5.4-py2.py3-none-any.whl
 create mode 100644 wheels/coverage-4.2-cp35-cp35m-linux_x86_64.whl
 create mode 100644 wheels/coverage_badge-0.1.2-py3-none-any.whl
 create mode 100644 wheels/django_rainbowtests-0.5.1-py3-none-any.whl
 create mode 100644 wheels/gunicorn-19.4.5-py2.py3-none-any.whl
 create mode 100644 wheels/kombu-3.0.37-py2.py3-none-any.whl
 create mode 100644 wheels/mccabe-0.4.0-py2.py3-none-any.whl
 create mode 100644 wheels/pep257-0.7.0-py2.py3-none-any.whl
 create mode 100644 wheels/pep8-1.7.0-py2.py3-none-any.whl
 create mode 100644 wheels/psycopg2-2.6.1-cp35-cp35m-linux_x86_64.whl
 create mode 100644 wheels/pyflakes-1.0.0-py2.py3-none-any.whl
 create mode 100644 wheels/pylama-7.0.7-py2.py3-none-any.whl
 create mode 100644 wheels/pytz-2016.7-py2.py3-none-any.whl
 create mode 100644 wheels/raven-5.26.0-py2.py3-none-any.whl
 create mode 100644 wheels/redis-2.10.5-py2.py3-none-any.whl
```<file_sep>VENV_PATH := $(HOME)/venv/bin
PROJ_NAME := falstartexample

runserver:
	$(VENV_PATH)/python manage.py runserver 0.0.0.0:8000

start:
	mkdir -p var
	$(VENV_PATH)/gunicorn --preload --pid var/gunicorn.pid \
		-D -b 127.0.0.1:8000 $(PROJ_NAME).wsgi:application

stop:
	kill `cat var/gunicorn.pid` || true

restart: stop start

pep8:
	$(VENV_PATH)/pep8 --exclude=*migrations*,*settings_local.py* \
		--max-line-length=119 --show-source  $(PROJ_NAME)/

pyflakes:
	$(VENV_PATH)/pylama --skip=*migrations* -l pyflakes $(PROJ_NAME)/

lint: pep8 pyflakes

test:
	$(VENV_PATH)/python manage.py test -v 2 --noinput

cover_test:
	$(VENV_PATH)/coverage run --source=$(PROJ_NAME) manage.py test -v 2 --noinput

cover_report:
	$(VENV_PATH)/coverage report -m
	$(VENV_PATH)/coverage html
	$(VENV_PATH)/coverage-badge > htmlcov/coverage.svg

ci_test: cover_test cover_report lint

wheel_install:
	$(VENV_PATH)/pip install --no-index -f wheels/ -r requirements.txt

runcelery:
	$(VENV_PATH)/celery -A $(PROJ_NAME) worker -l info -B -s ./var/celerybeat-schedule

runcelery_multi:
	$(VENV_PATH)/celery multi restart $(PROJ_NAME)_worker \
		-A $(PROJ_NAME) -l info -B -s ./var/celerybeat-schedule \
			--logfile="./var/celery_%n.log" \
			--pidfile="./var/celery_%n.pid"

stopcelery_multi:
	kill `cat var/celery_$(PROJ_NAME)_worker.pid` || true

restart_celery: stopcelery_multi runcelery_multi

<file_sep># vi: syntax=python
import os
import fabric

from inspect import getsource
from textwrap import dedent
from fabric.api import run, sudo, cd

fabric.state.env.colorize_errors = True
fabric.state.output['stdout'] = False

# task const variables
VARS = dict(
    current_user=fabric.state.env.user,

    # project settings
    project_name='falstartexample',
    user_data=dict(
        username='root',
        email='<EMAIL>',
        password='<PASSWORD>'
    ),

    # dirs configs
    templates_dir='./provision/templates',
    root_dir='/home/vagrant/proj',
    venv_path='/home/vagrant/venv',
    base_dir='/home/vagrant',

    # nginx config
    http_host='10.1.1.111',
    http_port='80',

    # database config
    db_name='falstartexample',
    db_password='<PASSWORD>',
    db_user='falstartexample_user',

    # locale conf
    locale='ru_RU',
    encoding='UTF-8',
)


def sentinel(sentinel_name=None):
    def sentinel_wrapp(function):
        hashed_func_name = '_'.join((function.__name__, str(hash(getsource(function)))))

        def wrapped():
            sentinel_path = '/usr/{}'.format(sentinel_name or hashed_func_name)
            if fabric.contrib.files.exists(sentinel_path):
                fabric.utils.warn('skip {}'.format(sentinel_name or hashed_func_name))
                return
            function()
            sudo('touch {}'.format(sentinel_path))
        return wrapped
    return sentinel_wrapp


def common():
    """ Common tasks """
    locale()
    apt_packages()
    python_packages()


@sentinel()
def locale():
    """ Set locale to enviroment """
    fabric.contrib.files.upload_template(
        'environment.j2', '/etc/environment',
        context=VARS, use_jinja=True, backup=False, use_sudo=True, template_dir=VARS['templates_dir'])
    sudo('localedef {locale}.{encoding} -i {locale} -f{encoding}'.format(**VARS))
    # sudo('locale-gen')


@sentinel()
def apt_packages():
    """ Install common packages """
    sudo('apt-get -y update')
    sudo('apt-get -y install libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev git redis-server')


@sentinel()
def python_packages():
    """ Install python components """

    sudo('apt-get -y install python-dev python-pip python-virtualenv build-essential '
         'libncurses5-dev libncursesw5-dev libreadline6-dev libgdbm-dev libsqlite3-dev '
         'libssl-dev libbz2-dev libexpat1-dev liblzma-dev zlib1g-dev libxml2-dev libxslt1-dev')

    with cd('/tmp'):
        # download python source code
        run('wget -O python.tgz https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tgz')
        # extract python tarball
        run('tar -xf python.tgz')
        run('mv Python-3.5.2 python')

    with cd('/tmp/python'):
        # configuring python 3.4 Makefile
        run('./configure --prefix=/usr/local/python-3.5.2')
        # compiling the python 3.4 source code and install
        run('make')
        sudo('make altinstall')
    sudo('rm /tmp/* -rf')
    # make link to python
    sudo('ln -sf /usr/local/python-3.5.2/bin/* /usr/local/bin/')



def nginx():
    """ Install and configure nginx tasks """
    nginx_install()
    # create nginx config file for project
    fabric.contrib.files.upload_template(
        'nginx-host.j2', '/etc/nginx/sites-available/{project_name}'.format(**VARS),
        context=VARS, use_jinja=True, backup=False, use_sudo=True, template_dir=VARS['templates_dir'])
    # make s-link to enabled sites
    sudo('ln -sf /etc/nginx/sites-available/{project_name} /etc/nginx/sites-enabled/{project_name}'.format(**VARS))
    # restart nginx
    sudo('service nginx restart')


@sentinel()
def nginx_install():
    """ Install nginx """
    # install nginx
    sudo('apt-get -y install nginx')


@sentinel()
def database():
    """ Install database tasks """
    # install postgres apt
    sudo('apt-get -y install postgresql postgresql-server-dev-all python-psycopg2')
    # make postgers password
    with fabric.context_managers.settings(warn_only=True):
        commands = (
            'CREATE USER {db_user};',
            'ALTER USER {db_user} WITH PASSWORD \'{<PASSWORD>}\';',
            'ALTER USER {db_user} CREATEDB;',
            'CREATE DATABASE {db_name};',
            'GRANT ALL PRIVILEGES ON DATABASE {db_name} TO {db_user};',
        )
        for command in commands:
            run('sudo -u postgres psql -c "%s"' % command.format(**VARS))



def app():
    """ Run application tasks """
    with cd(VARS['root_dir']):
        # Create venv and install requirements
        run('pyvenv-3.5 {venv_path}'.format(**VARS))
        # Install required python packages with pip from wheels archive
        run('make wheel_install')
        # run app tasks for devserver start
        # Copy settings local
        run('cd {project_name} && cp settings_local.py.example settings_local.py'.format(**VARS))


def localserver():
    with cd(VARS['root_dir']):
        # collect static files
        for command in ('migrate --noinput', 'collectstatic --noinput', ):  # 'compilemessages', ):
            run('{venv_path}/bin/python manage.py {command}'.format(command=command, **VARS))
        # make root dir available to read
        # sudo('chmod 755 {base_dir}/static -R'.format(**VARS))
        # Create user
        create_user_py = dedent('''\
            from django.contrib.auth import get_user_model
            User = get_user_model()
            User.objects.create_superuser(**{user_data})
        ''').format(**VARS)

        run('echo "{create_user_py}" | {venv_path}/bin/python manage.py shell'.format(
            create_user_py=create_user_py, **VARS))
        run('mkdir var -p')

        # Start celery and runserver
        run('make start', pty=False)
        run('make runcelery_multi', pty=False)


<file_sep>Django==1.10.2
django-rainbowtests==0.5.1
gunicorn==19.4.5
pep8==1.7.0
coverage==4.2
coverage-badge==0.1.2
pylama==7.0.7
psycopg2==2.6.1
Celery==3.1.23
redis==2.10.5
raven==5.26.0
