3
from tempfile import mkdtemp, mktemp
4
from django.core import management
5
from fabric.api import run, sudo, local, put, env, settings, abort, cd
6
from fabric.contrib.console import confirm
7
from fabric.contrib.files import append, contains
8
from fabric.utils import abort
9
from deployment import (settings_staging,
14
VALID_DEPLOYMENT_TYPES = ['production',
19
env.key_filename = '/home/ubuntu/alesage_lcy01.key'
21
def apt_get_everything():
22
"""apt-get everything required to be a qa_dashboard."""
23
sudo("apt-get install -y bzr apache2 libapache2-mod-wsgi \
24
python-django postgresql python-psycopg2 python-pip python-tz \
25
python-django-auth-openid django-tables python-django-celery \
26
python-numpy python-yaml python-mock python-django-south \
30
def restart_postgres():
31
"""Restart our fav DB server."""
32
sudo("service postgresql restart")
35
def ubuntu_postgres_user_exists():
36
"""Does the postgres user exist and can I have her phone number?"""
37
result = sudo("psql postgres -tAc \"SELECT 1 FROM pg_roles WHERE rolname='ubuntu'\"",
39
return int(result) == 1
42
def create_ubuntu_postgres_user():
43
"""Create 'ubuntu' postgres user."""
45
with settings(warn_only=True):
46
sudo("createuser -U postgres -s ubuntu -P", user='postgres')
47
sudo("createdb ubuntu", user='postgres')
50
def database_exists(name='qa_dashboard'):
51
"""Does the database exist?"""
52
result = sudo("psql -tAc \"SELECT * FROM pg_database WHERE datname='{}';\"".format(name),
57
def destroy_database(name='qa_dashboard'):
58
"""Destroy postgresql qa_dashboard database."""
59
with settings(warn_only=True):
60
# we could warn on this if it doesn't exist (but we don't expect to)
61
sudo("dropdb {}".format(name),
65
def create_database(name='qa_dashboard'):
66
"""Create a fresh db for user ubuntu."""
67
sudo("createdb -E utf8 -O ubuntu {} -T template0".format(name),
71
def adjust_pg_hba_conf():
72
"""We need md5 password checking for localhost."""
74
# TODO: this sed dinna work under fabric WTF:
75
# sudo sed 's/^\(local\s*all\s*all\s*\)\(.*\)$/\1md5/' /etc/postgresql/9.1/main/pg_hba.conf
76
# . . . so we're just copying a baked file
77
put("./deployment/pg_hba.conf", "/etc/postgresql/9.3/main/", use_sudo=True)
81
def setup_database(name='qa_dashboard'):
82
"""Create postgresql qa_dashboard user and database.
84
Name defaults to 'qa_dashboard' for production, suggest
85
'qa_dashboard-staging' for staging.
88
if not ubuntu_postgres_user_exists():
89
create_ubuntu_postgres_user()
90
if database_exists(name):
91
destroy_database(name)
96
def checkout_qa_dashboard(install_dir, branch="lp:helipad"):
97
"""Checkout branch into 'qa_dashboard' in the user's home dir.
99
Bazaar and fabric don't get along so we can't just bzr branch,
100
instead cp from a local checkout.
102
# blow away whatever's there at the install path
103
sudo("rm -rf {}/*".format(install_dir))
104
sudo("mkdir -p {}".format(install_dir))
105
sudo("chown ubuntu {}".format(install_dir))
107
# get a local checkout of the source, pack, and ship
109
tmp_install_dir = os.path.join(tmp_dir, 'qa_dashboard')
110
local("bzr branch {} {}".format(branch, tmp_install_dir))
111
# this is kind-of silly but the tar -C option wasn't working with globbing
112
orig_dir = os.getcwd()
113
os.chdir(tmp_install_dir)
114
local("tar --exclude fabfile.pyc --overwrite -czvf /tmp/qa_dashboard-source.tar.gz *")
116
put("/tmp/qa_dashboard-source.tar.gz",
119
with cd(install_dir):
120
run("tar -xvf qa_dashboard-source.tar.gz")
121
run("rm {}".format(os.path.join(install_dir, "qa_dashboard-source.tar.gz")))
122
local("rm -rf {}".format(tmp_install_dir))
124
# set perms so that www-data can access
125
sudo("chown -R ubuntu:qa_dashboard {}".format(install_dir))
126
sudo("chmod -R g+rw {}".format(install_dir))
129
def restart_apache():
130
"""Restart our fav webserver."""
131
sudo("service apache2 restart")
134
def configure_apache(apache_config_filepath):
135
"""Configure apache2: copy our site config, set up perms, etc.
137
'deployment/qa_dashboard-staging', e.g.
139
basename = os.path.basename(apache_config_filepath)
140
sudo("cp {} /etc/apache2/sites-available/{}.conf".format(
141
apache_config_filepath,
143
sudo("adduser www-data qa_dashboard")
144
# we'll take the last term of the apache config path as the site name to enable
145
site_name = os.path.split(apache_config_filepath)[-1]
146
sudo("a2ensite {}".format(site_name))
151
"""Create a qa_dashboard group and add ubuntu to it.
153
This facilitates apache access.
155
with settings(warn_only=True):
156
sudo("addgroup qa_dashboard")
157
sudo("adduser ubuntu qa_dashboard")
160
def copy_local_settings(install_dir,
161
settings_filename="settings_production.py"):
162
"""Copy settings into place."""
163
sudo("cp {} {}".format(
164
os.path.join(install_dir,
167
os.path.join(install_dir,
169
"local_settings.py")),
173
def collect_static_media(install_dir):
174
"""Use the Django utility to collect all of our static files."""
176
with cd(install_dir):
177
sudo("python manage.py collectstatic --noinput", user='ubuntu')
180
def setup_cron_job(install_dir):
181
"""Add our qa-dashboard-update.sh to crontab."""
183
cron_job_line = "42 * * * * {}/scripts/qa-dashboard-update.sh".format(install_dir)
184
tmp_cron_filename = mktemp()
185
# our crontab might be empty; ignore that error
186
with settings(warn_only=True):
187
run("crontab -l 2>/dev/null > {}".format(tmp_cron_filename),)
188
if contains(tmp_cron_filename, cron_job_line):
189
print cron_job_line + " already in crontab."
191
append(tmp_cron_filename, cron_job_line)
192
run("crontab {}".format(tmp_cron_filename))
193
run("rm {}".format(tmp_cron_filename))
196
def deploy(deployment_type, branch="lp:~helipad-team/helipad/coverage"):
197
"""Push this branch to the production site.
199
deployment_type should be one of 'production', 'staging', or 'testing'.
202
if deployment_type not in VALID_DEPLOYMENT_TYPES:
203
abort("Deployment must be one of {}.".format(VALID_DEPLOYMENT_TYPES))
204
install_dir = {'production': settings_production.INSTALL_PATH,
205
'staging': settings_staging.INSTALL_PATH,
206
'testing': settings_testing.INSTALL_PATH}[deployment_type]
207
checkout_qa_dashboard(install_dir, branch)
208
apache_config_filename = {'production': 'qa_dashboard',
209
'staging': 'qa_dashboard-staging',
210
'testing': 'qa_dashboard-testing'}[deployment_type]
212
os.path.join(install_dir,
214
apache_config_filename))
215
setup_cron_job(install_dir)
216
# compose a settings_filename, e.g. settings_testing.py
217
settings_filename = "settings_{}.py".format(deployment_type)
218
copy_local_settings(install_dir,
220
collect_static_media(install_dir)
221
with cd(install_dir):
222
run("python manage.py syncdb")
223
run("python manage.py migrate")
226
def setup(deployment_type, branch="lp:~helipad-team/helipad/coverage"):
227
"""Setup the qa_dashboard site on a new server.
229
deployment_type should be one of 'production', 'staging', or 'testing'.
234
if deployment_type not in VALID_DEPLOYMENT_TYPES:
235
abort("deployment_type must be one of {}.".format(VALID_DEPLOYMENT_TYPES))
238
database_name = {'production': 'qa_dashboard',
239
'staging': 'qa_dashboard-staging',
240
'testing': 'qa_dashboard-testing'}[deployment_type]
241
setup_database(database_name)
242
deploy(deployment_type, branch=branch)