~allanlesage/qa-coverage-dashboard/simplify-extractor

« back to all changes in this revision

Viewing changes to fabfile.py

  • Committer: chris.gagnon
  • Date: 2014-02-25 15:36:32 UTC
  • mfrom: (741.1.9 deployment)
  • Revision ID: chris.gagnon@canonical.com-20140225153632-kj9gddp684q9xhis
merge with trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import os
 
2
import logging
 
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,
 
10
                        settings_production,
 
11
                        settings_testing)
 
12
 
 
13
 
 
14
VALID_DEPLOYMENT_TYPES = ['production',
 
15
                          'staging',
 
16
                          'testing']
 
17
 
 
18
env.user = 'ubuntu'
 
19
env.key_filename = '/home/ubuntu/alesage_lcy01.key'
 
20
 
 
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 \
 
27
          python-tastypie")
 
28
 
 
29
 
 
30
def restart_postgres():
 
31
    """Restart our fav DB server."""
 
32
    sudo("service postgresql restart")
 
33
 
 
34
 
 
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'\"",
 
38
                  user='postgres')
 
39
    return int(result) == 1
 
40
 
 
41
 
 
42
def create_ubuntu_postgres_user():
 
43
    """Create 'ubuntu' postgres user."""
 
44
 
 
45
    with settings(warn_only=True):
 
46
        sudo("createuser -U postgres -s ubuntu -P", user='postgres')
 
47
        sudo("createdb ubuntu", user='postgres')
 
48
 
 
49
 
 
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),
 
53
                  user='postgres')
 
54
    return result != ""
 
55
 
 
56
 
 
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),
 
62
             user='postgres')
 
63
 
 
64
 
 
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),
 
68
         user='postgres')
 
69
 
 
70
 
 
71
def adjust_pg_hba_conf():
 
72
    """We need md5 password checking for localhost."""
 
73
 
 
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)
 
78
    restart_postgres()
 
79
 
 
80
 
 
81
def setup_database(name='qa_dashboard'):
 
82
    """Create postgresql qa_dashboard user and database.
 
83
 
 
84
    Name defaults to 'qa_dashboard' for production, suggest
 
85
    'qa_dashboard-staging' for staging.
 
86
    """
 
87
    adjust_pg_hba_conf()
 
88
    if not ubuntu_postgres_user_exists():
 
89
        create_ubuntu_postgres_user()
 
90
    if database_exists(name):
 
91
        destroy_database(name)
 
92
    create_database(name)
 
93
    restart_postgres()
 
94
 
 
95
 
 
96
def checkout_qa_dashboard(install_dir, branch="lp:helipad"):
 
97
    """Checkout branch into 'qa_dashboard' in the user's home dir.
 
98
 
 
99
    Bazaar and fabric don't get along so we can't just bzr branch,
 
100
    instead cp from a local checkout.
 
101
    """
 
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))
 
106
 
 
107
    # get a local checkout of the source, pack, and ship
 
108
    tmp_dir = mkdtemp()
 
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 *")
 
115
    os.chdir(orig_dir)
 
116
    put("/tmp/qa_dashboard-source.tar.gz",
 
117
        install_dir,
 
118
        use_sudo=True)
 
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))
 
123
 
 
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))
 
127
 
 
128
 
 
129
def restart_apache():
 
130
    """Restart our fav webserver."""
 
131
    sudo("service apache2 restart")
 
132
 
 
133
 
 
134
def configure_apache(apache_config_filepath):
 
135
    """Configure apache2: copy our site config, set up perms, etc.
 
136
 
 
137
    'deployment/qa_dashboard-staging', e.g.
 
138
    """
 
139
    basename = os.path.basename(apache_config_filepath)
 
140
    sudo("cp {} /etc/apache2/sites-available/{}.conf".format(
 
141
            apache_config_filepath,
 
142
            basename))
 
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))
 
147
    restart_apache()
 
148
 
 
149
 
 
150
def setup_users():
 
151
    """Create a qa_dashboard group and add ubuntu to it.
 
152
 
 
153
    This facilitates apache access.
 
154
    """
 
155
    with settings(warn_only=True):
 
156
        sudo("addgroup qa_dashboard")
 
157
        sudo("adduser ubuntu qa_dashboard")
 
158
 
 
159
 
 
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,
 
165
                         'deployment',
 
166
                         settings_filename),
 
167
            os.path.join(install_dir,
 
168
                         "qa_dashboard",
 
169
                         "local_settings.py")),
 
170
         user='ubuntu')
 
171
 
 
172
 
 
173
def collect_static_media(install_dir):
 
174
    """Use the Django utility to collect all of our static files."""
 
175
 
 
176
    with cd(install_dir):
 
177
        sudo("python manage.py collectstatic --noinput", user='ubuntu')
 
178
 
 
179
 
 
180
def setup_cron_job(install_dir):
 
181
    """Add our qa-dashboard-update.sh to crontab."""
 
182
 
 
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."
 
190
    else:
 
191
        append(tmp_cron_filename, cron_job_line)
 
192
        run("crontab {}".format(tmp_cron_filename))
 
193
        run("rm {}".format(tmp_cron_filename))
 
194
 
 
195
 
 
196
def deploy(deployment_type, branch="lp:~helipad-team/helipad/coverage"):
 
197
    """Push this branch to the production site.
 
198
 
 
199
    deployment_type should be one of 'production', 'staging', or 'testing'.
 
200
    """
 
201
 
 
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]
 
211
    configure_apache(
 
212
        os.path.join(install_dir,
 
213
                     'deployment',
 
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,
 
219
                        settings_filename)
 
220
    collect_static_media(install_dir)
 
221
    with cd(install_dir):
 
222
        run("python manage.py syncdb")
 
223
        run("python manage.py migrate")
 
224
 
 
225
 
 
226
def setup(deployment_type, branch="lp:~helipad-team/helipad/coverage"):
 
227
    """Setup the qa_dashboard site on a new server.
 
228
 
 
229
    deployment_type should be one of 'production', 'staging', or 'testing'.
 
230
 
 
231
    NOTE: DROPS DB.
 
232
    """
 
233
 
 
234
    if deployment_type not in VALID_DEPLOYMENT_TYPES:
 
235
        abort("deployment_type must be one of {}.".format(VALID_DEPLOYMENT_TYPES))
 
236
    apt_get_everything()
 
237
    setup_users()
 
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)