You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

340 lines
9.7 KiB

import os
import sys
from functools import wraps
from getpass import getpass, getuser
from glob import glob
from contextlib import contextmanager
from fabric.api import env, cd, prefix, sudo as _sudo, run as _run, hide, local, put
from fabric.contrib.files import exists, upload_template
from fabric.colors import yellow, green, blue, red
###########
# Config #
###########
config = {
'server_name' : 'lms.skillbox.ru',
'hosts' : ['lms.skillbox.ru'],
'key_path' : '~/.ssh/hev7.pub',
'user' : 'root',
'password' : 'nu5Xefise',
'project_name' : 'skillbox',
'db_password' : 'super3360',
'manage_py_path' : '',
'settings_path' : 'skillbox',
'repository_type' : 'git',
'repository_url' : 'git@gitlab.com:skillbox/go.skillbox.ru.git',
'aws_key' : '',
'aws_secret' : ''
}
env.server_name = config['server_name']
env.key_filename = config['key_path']
env.hosts = config['hosts']
env.user = config['user']
env.project_name = config['project_name']
env.db_name = env.project_name.lower()
env.db_password = config['db_password']
env.project_path = '/var/www/%s' % env.project_name
#env.application_path = '/var/www/%s/%s' % (env.project_name, config['manage_py_path'])
env.application_path = '/var/www/%s' % env.project_name
env.virtualenv_path = '%s/env/bin/activate' % env.project_path
env.repository_type = config['repository_type']
env.repository_url = config['repository_url']
env.manage = "%s/env/bin/python %s/manage.py" % (env.project_path, env.application_path)
env.settings_path = env.application_path if not len(config['settings_path']) else '%s/%s' % (env.application_path, config['settings_path'])
env.aws_key = config['aws_key']
env.aws_secret = config['aws_secret']
templates = {
'django_settings' : {
'local_path' : 'conf/live_settings.py',
'remote_path' : '%s/local_settings.py' % env.settings_path
},
'uwsgi' : {
'local_path' : 'conf/uwsgi_prod.ini',
'remote_path' : '%s/uwsgi_prod.ini' %env.project_path
},
'nginx' : {
'local_path' : 'conf/nginx.conf',
'remote_path' : '/etc/nginx/sites-enabled/%s.conf' % env.project_name,
'reload_command' : '/etc/init.d/nginx restart'
},
"supervisor": {
"local_path": "conf/supervisor.conf",
"remote_path": "/etc/supervisor/conf.d/%s.conf" % env.project_name,
"reload_command": "supervisorctl reload",
}
}
def _print(output):
print
print output
print
def print_command(command):
_print(blue("$ ", bold=True) +
yellow(command, bold=True) +
red(" ->", bold=True))
def run(command, show=True):
"""
Run a shell comand on the remote server.
"""
if show:
print_command(command)
with hide("running"):
return _run(command)
def sudo(command, show=True):
"""
Run a command as sudo.
"""
if show:
print_command(command)
with hide("running"):
return _sudo(command)
def psql(sql, show=True):
"""
Executes a psql command
"""
out = run('sudo -u postgres psql -c "%s"' % sql)
if show:
print_command(sql)
return out
def pip(modules):
"""
Install the Python modules passed as arguments with pip
"""
with virtualenv():
run('pip install %s' % modules)
def log_call(func):
@wraps(func)
def logged(*args, **kawrgs):
header = "-" * len(func.__name__)
_print(green("\n".join([header, func.__name__, header]), bold=True))
return func(*args, **kawrgs)
return logged
@contextmanager
def virtualenv():
"""
Run commands within the project's virtualenv.
"""
with cd('%s/env/bin/' % env.project_path):
with prefix("source %s/env/bin/activate" % env.project_path):
yield
@contextmanager
def project():
"""
Run commands within the project's directory.
"""
with virtualenv():
with cd(env.application_path):
yield
def manage(command):
"""
Run a Django management command.
"""
return run("%s %s" % (env.manage, command))
@log_call
def generate_ssh_key():
"""
Generates a key pair and displays the public key
"""
run('ssh-keygen -t rsa')
run('cat ~/.ssh/id_rsa.pub')
@log_call
def install_aptitude():
sudo('apt-get install aptitude -y')
@log_call
def upgrade():
"""
Updates the repository definitions and upgrades the server
"""
sudo('aptitude update -y')
sudo('aptitude upgrade -y')
def upload_template_and_reload(name):
template_settings = templates[name]
local_path = template_settings['local_path']
remote_path = template_settings['remote_path']
reload_command = template_settings.get('reload_command')
owner = template_settings.get("owner")
mode = template_settings.get("mode")
print '%s to %s' % (local_path, remote_path)
upload_template(local_path, remote_path, env, use_sudo=False, backup=False)
if owner:
sudo("chown %s %s" % (owner, remote_path))
if mode:
sudo("chmod %s %s" % (mode, remote_path))
if reload_command:
sudo(reload_command)
@log_call
def install_base():
"""
Installs the base software required to deploy an application
"""
install_aptitude()
sudo(
"aptitude install gcc make git-core nginx postgresql memcached python-dev\
python-setuptools supervisor postgresql-server-dev-all libxml2-dev\
libxslt-dev -y"# redis-server rabbitmq-server -y"
)
#run('wget http://www.ijg.org/files/jpegsrc.v8d.tar.gz')
#run('tar xvzf jpegsrc.v8d.tar.gz')
#with cd('jpeg-8d'):
# run('./configure')
# run('make')
# sudo('make install')
#run('wget http://download.savannah.gnu.org/releases/freetype/freetype-2.4.10.tar.gz')
#run('tar xvzf freetype-2.4.10.tar.gz')
#with cd('freetype-2.4.10'):
# run('./configure')
# run('make')
# sudo('make install')
#run('wget http://zlib.net/zlib-1.2.8.tar.gz')
#run('tar xvzf zlib-1.2.8.tar.gz')
#with cd('zlib-1.2.8'):
# run('./configure')
# run('make')
# sudo('make install')
sudo('easy_install pip')
sudo('pip install virtualenv mercurial uwsgi')
run('echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config')
run('echo -e "Host bitbucket.org\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config')
#sudo('rabbitmqctl add_user %s %s' % (env.project_name, env.db_name))
#sudo('rabbitmqctl add_vhost %s' % env.project_name)
#sudo(
# 'rabbitmqctl set_permissions -p %s %s ".*" ".*" ".*"' %
# (env.project_name, env.project_name)
#)
@log_call
def _create_database(name, password):
psql("CREATE USER %s WITH ENCRYPTED PASSWORD '%s';" % (name, password))
psql("ALTER USER %s CREATEDB;" % name)
psql("CREATE DATABASE %s WITH OWNER %s ENCODING='UTF8';" % (env.project_name, env.project_name))
@log_call
def create_database():
"""
Creates a database and a database user with the project name and the specified password
"""
_create_database(env.db_name, env.db_password)
@log_call
def fetch():
with cd(env.project_path):
run(
'%s pull %s' % (
env.repository_type,
'-u' if env.repository_type == 'hg' else ''
)
)
with virtualenv():
#manage('migrate --run-syncdb --noinput')
#manage('migrate')
#manage("migrate --noinput")
manage("collectstatic -v 0 --noinput")
#upload_template_and_reload('django_settings')
#upload_template_and_reload('gunicorn')
upload_template_and_reload('uwsgi')
upload_template_and_reload('nginx')
upload_template_and_reload('supervisor')
@log_call
def create():
"""
Stages the application on the server
"""
sudo('rm -r %s -f' % env.project_path)
sudo('chown %s /var' % 'www-data')
with cd('/var'):
run('mkdir -p www')
with cd('/var/www'):
run('%s clone %s %s' %(env.repository_type, env.repository_url, env.project_path))
sudo('ln -s /var/www/media %s' % env.project_path)
with cd(env.project_path):
run("virtualenv -p python3 env --distribute")
with virtualenv():
run('pip install -r %s/requirements.txt' % env.project_path)
#pip('python-memcached')
#upload_template_and_reload('django_settings')
#upload_template_and_reload('gunicorn')
upload_template_and_reload('uwsgi')
upload_template_and_reload('nginx')
upload_template_and_reload('supervisor')
with virtualenv():
#manage('migrate --run-syncdb --noinput')
#manage('migrate --list')
#manage("migrate --noinput")
manage("collectstatic -v 0 --noinput")
#if exists('%sgunicorn.pid'):
# sudo("kill -HUP 'cat %sgunicorn.pid'" % env.project_path)
#else:
# sudo("supervisorctl start %s:gunicorn" % env.project_name)
@log_call
def install_all():
install_aptitude()
upgrade()
install_base()
create_database()
create()
@log_call
def create_superuser():
with virtualenv():
manage('createsuperuser')
def send_key():
put('~/.ssh/id_rsa', '~/.ssh/id_rsa')
put('~/.ssh/id_rsa.pub', '~/.ssh/id_rsa.pub')
run('chmod 600 ~/.ssh/id_rsa')
run('chmod 600 ~/.ssh/id_rsa.pub')
"""
def vagrant():
# change from the default user to 'vagrant'
env.user = 'vagrant'
env.password = 'vagrant'
env.project_path = '/vagrant'
env.application_path = '/vagrant'
env.virtualenv_path = '%s/env/bin/activate' % env.project_path
env.manage = "%s/env/bin/python %s/manage.py" % (env.project_path, env.application_path)
# connect to the port-forwarded ssh
env.hosts = ['127.0.0.1:2222']
# use vagrant ssh key
result = local('vagrant ssh-config | grep IdentityFile', capture=True)
env.key_filename = result.split()[1][1:-1]
"""