|
1
|
|
|
""" |
|
2
|
|
|
Fabfile to setup and deploy gage-web |
|
3
|
|
|
""" |
|
4
|
|
|
from fabric.api import cd, run, local, env, sudo, put, prompt, lcd, prefix |
|
5
|
|
|
from fabric.contrib.console import confirm |
|
6
|
|
|
from fabtools import require |
|
7
|
|
|
import fabtools |
|
8
|
|
|
|
|
9
|
|
|
# uses a file called fabhosts where servers can be defined but gitignored |
|
10
|
|
|
# looks like |
|
11
|
|
|
# |
|
12
|
|
|
# from fabric.api import env |
|
13
|
|
|
# |
|
14
|
|
|
# def prod(): |
|
15
|
|
|
# env.user = 'username' |
|
16
|
|
|
# env.hosts = ['server1', 'server2'] |
|
17
|
|
|
# |
|
18
|
|
|
try: |
|
19
|
|
|
from fabhosts import (prod, # noqa |
|
20
|
|
|
register_deployment, |
|
21
|
|
|
WWW_DIR, |
|
22
|
|
|
ENV_DIR, |
|
23
|
|
|
USER, |
|
24
|
|
|
GROUP, |
|
25
|
|
|
DB, |
|
26
|
|
|
DB_USER, |
|
27
|
|
|
DB_PASSWORD, |
|
28
|
|
|
GIT_DIR) |
|
29
|
|
|
except ImportError: |
|
30
|
|
|
pass |
|
31
|
|
|
|
|
32
|
|
|
LOCAL_APP_DIR = '.' |
|
33
|
|
|
LOCAL_CONFIG_DIR = LOCAL_APP_DIR + '/server-config' |
|
34
|
|
|
|
|
35
|
|
|
|
|
36
|
|
|
def apt_upgrade(): |
|
37
|
|
|
""" |
|
38
|
|
|
Run apt-get upgrade |
|
39
|
|
|
""" |
|
40
|
|
|
require.deb.uptodate_index(max_age={'day': 1}) |
|
41
|
|
|
sudo('apt-get upgrade') |
|
42
|
|
|
|
|
43
|
|
|
|
|
44
|
|
|
def create_user(): |
|
45
|
|
|
""" |
|
46
|
|
|
Create a gage_www user for running gage-web |
|
47
|
|
|
""" |
|
48
|
|
|
require.groups.group(GROUP) |
|
49
|
|
|
require.users.user(USER, group=GROUP, system=True) |
|
50
|
|
|
|
|
51
|
|
|
|
|
52
|
|
|
def create_www_folder(): |
|
53
|
|
|
""" |
|
54
|
|
|
Folder for gage-web to run from |
|
55
|
|
|
""" |
|
56
|
|
|
require.directory(WWW_DIR, |
|
57
|
|
|
use_sudo=True, |
|
58
|
|
|
owner=USER) |
|
59
|
|
|
|
|
60
|
|
|
|
|
61
|
|
|
def create_venv(): |
|
62
|
|
|
""" |
|
63
|
|
|
Create virutalenv for gage-web |
|
64
|
|
|
""" |
|
65
|
|
|
require.python.virtualenv(ENV_DIR, |
|
66
|
|
|
use_sudo=True) |
|
67
|
|
|
|
|
68
|
|
|
|
|
69
|
|
|
def install_system_requirements(): |
|
70
|
|
|
""" |
|
71
|
|
|
Install required system packages |
|
72
|
|
|
""" |
|
73
|
|
|
require.deb.packages(['python', |
|
74
|
|
|
'python-dev', |
|
75
|
|
|
'python-pip', |
|
76
|
|
|
'python-virtualenv', |
|
77
|
|
|
'nginx', |
|
78
|
|
|
'postgresql-9.4', |
|
79
|
|
|
'postgresql-9.4-postgis-2.1', |
|
80
|
|
|
'postgresql-server-dev-9.4', |
|
81
|
|
|
'libpq-dev', |
|
82
|
|
|
'git', |
|
83
|
|
|
'gdal-bin', |
|
84
|
|
|
'gfortran', |
|
85
|
|
|
'python-gdal', |
|
86
|
|
|
'python-numpy', |
|
87
|
|
|
'python-scipy', |
|
88
|
|
|
'python-pandas', |
|
89
|
|
|
'libblas-dev', |
|
90
|
|
|
'liblapack-dev', |
|
91
|
|
|
'libgdal-dev', |
|
92
|
|
|
'supervisor', |
|
93
|
|
|
'redis-server', |
|
94
|
|
|
'libxslt1.dev', |
|
95
|
|
|
'libjpeg8-dev', |
|
96
|
|
|
'libjpeg-dev', |
|
97
|
|
|
'libfreetype6-dev', |
|
98
|
|
|
'zlib1g-dev', |
|
99
|
|
|
'libpng12-dev']) |
|
100
|
|
|
sudo('export CPLUS_INCLUDE_PATH=/usr/include/gdal') |
|
101
|
|
|
sudo('export C_INCLUDE_PATH=/usr/include/gdal') |
|
102
|
|
|
|
|
103
|
|
|
|
|
104
|
|
|
def create_database(): |
|
105
|
|
|
""" |
|
106
|
|
|
Create database and setup postgis |
|
107
|
|
|
""" |
|
108
|
|
|
output = sudo('psql -lqt | cut -d \| -f 1', user='postgres') |
|
109
|
|
|
if DB in output: |
|
110
|
|
|
print('{DB} database found!'.format(DB=DB)) |
|
111
|
|
|
else: |
|
112
|
|
|
print('{DB} not found! Creating DB'.format(DB=DB)) |
|
113
|
|
|
# require.postgres.user(DB_USER, password=DB_PASSWORD) |
|
114
|
|
|
sudo("""psql -c "CREATE USER '{DB_USER}' NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN UNENCRYPTED PASSWORD '{DB_PASSWORD}';""".format(DB_USER=DB_USER, DB_PASSWORD=DB_PASSWORD), |
|
115
|
|
|
user='postgres') |
|
116
|
|
|
# require.postgres.database(DB, owner=DB_USER) |
|
117
|
|
|
sudo('createdb --owner {DB_USER} {DB}'.format(DB_USER=DB_USER, DB=DB), |
|
118
|
|
|
user='postgres') |
|
119
|
|
|
sudo('psql -d {DB} -c "CREATE EXTENSION postgis;"'.format(DB=DB), |
|
120
|
|
|
user='postgres') |
|
121
|
|
|
sudo('psql -d {DB} -c "CREATE EXTENSION postgis_topology;"'.format(DB=DB), |
|
122
|
|
|
user='postgres') |
|
123
|
|
|
|
|
124
|
|
|
|
|
125
|
|
|
def configure_git(): |
|
126
|
|
|
""" |
|
127
|
|
|
1. Setup bare Git Repo |
|
128
|
|
|
2. Create post-recieve hook |
|
129
|
|
|
""" |
|
130
|
|
|
require.directory(GIT_DIR, use_sudo=True) |
|
131
|
|
|
with cd(GIT_DIR): |
|
132
|
|
|
sudo('mkdir gage-web.git') |
|
133
|
|
|
with cd('gage-web.git'): |
|
134
|
|
|
sudo('git init --bare') |
|
135
|
|
|
with lcd(LOCAL_CONFIG_DIR): |
|
136
|
|
|
with cd('hooks'): |
|
137
|
|
|
put('./post-receive', './', use_sudo=True) |
|
138
|
|
|
sudo('chmod +x post-receive') |
|
139
|
|
|
with lcd(LOCAL_APP_DIR): |
|
140
|
|
|
local( |
|
141
|
|
|
'git remote add production {user}@{server}:{GIT_DIR}/gage-web.git' |
|
142
|
|
|
.format(user=env.user, server=env.host_string, GIT_DIR=GIT_DIR)) |
|
143
|
|
|
|
|
144
|
|
|
|
|
145
|
|
|
def deploy(): |
|
146
|
|
|
""" |
|
147
|
|
|
Push current master to production and restart gunicorn |
|
148
|
|
|
""" |
|
149
|
|
|
with lcd(LOCAL_APP_DIR): |
|
150
|
|
|
local('git push production master') |
|
151
|
|
|
sudo('supervisorctl restart gage:*') |
|
152
|
|
|
register_deployment(LOCAL_APP_DIR) |
|
153
|
|
|
|
|
154
|
|
|
|
|
155
|
|
|
def install_requirements(): |
|
156
|
|
|
""" |
|
157
|
|
|
Install requirements into virtualenv |
|
158
|
|
|
""" |
|
159
|
|
|
with fabtools.python.virtualenv(ENV_DIR): |
|
160
|
|
|
with cd(WWW_DIR): |
|
161
|
|
|
require.python.requirements('requirements.txt') |
|
162
|
|
|
|
|
163
|
|
|
|
|
164
|
|
|
def install_config_files(): |
|
165
|
|
|
""" |
|
166
|
|
|
Put config files for gunicorn, supervisord, nginx |
|
167
|
|
|
""" |
|
168
|
|
|
# host-export |
|
169
|
|
|
with cd(WWW_DIR + '/server-config'): |
|
170
|
|
|
require.file('host-export', source=LOCAL_CONFIG_DIR+'/host-export') |
|
171
|
|
|
sudo('chmod +x host-export') |
|
172
|
|
|
# gunicorn |
|
173
|
|
|
with cd('/home/www'): |
|
174
|
|
|
fabtools.files.upload_template( |
|
175
|
|
|
LOCAL_CONFIG_DIR + '/gunicorn-start-gage', |
|
176
|
|
|
'.', |
|
177
|
|
|
use_sudo=True, |
|
178
|
|
|
use_jinja=True, |
|
179
|
|
|
user=USER, |
|
180
|
|
|
context={ |
|
181
|
|
|
'WWW_DIR': WWW_DIR, |
|
182
|
|
|
'ENV_DIR': ENV_DIR, |
|
183
|
|
|
'USER': USER, |
|
184
|
|
|
'GROUP': GROUP |
|
185
|
|
|
}, |
|
186
|
|
|
chown=True), |
|
187
|
|
|
sudo('chmod +x gunicorn-start-gage') |
|
188
|
|
|
# supervisord |
|
189
|
|
|
with cd('/etc/supervisor/conf.d/'): |
|
190
|
|
|
require.file('gage-web.conf', |
|
191
|
|
|
source=LOCAL_CONFIG_DIR+'/gage-web.conf', |
|
192
|
|
|
use_sudo=True) |
|
193
|
|
|
require.directory('/home/www/logs/gage-web/') |
|
194
|
|
|
sudo('supervisorctl reread') |
|
195
|
|
|
sudo('supervisorctl update') |
|
196
|
|
|
# nginx |
|
197
|
|
|
with cd('/etc/nginx/sites-available'): |
|
198
|
|
|
require.file('gage-web', |
|
199
|
|
|
source=LOCAL_CONFIG_DIR+'/gage-web', |
|
200
|
|
|
use_sudo=True) |
|
201
|
|
|
sudo('ln -s /etc/nginx/sites-available/gage-web' + |
|
202
|
|
|
' /etc/nginx/sites-enabled/gage-web') |
|
203
|
|
|
sudo('service nginx configtest') |
|
204
|
|
|
sudo('service nginx restart') |
|
205
|
|
|
|
|
206
|
|
|
|
|
207
|
|
|
def upgrade_db_schema(): |
|
208
|
|
|
""" |
|
209
|
|
|
With manage.py setup database |
|
210
|
|
|
""" |
|
211
|
|
|
with prefix('source {ENV_DIR}/bin/activate'.format(ENV_DIR=ENV_DIR)): |
|
212
|
|
|
with prefix('source {WWW_DIR}/server-config/host-export'.format(WWW_DIR=WWW_DIR)): |
|
213
|
|
|
with cd(WWW_DIR): |
|
214
|
|
|
sudo('python manage.py db upgrade') |
|
215
|
|
|
|
|
216
|
|
|
|
|
217
|
|
|
def create_roles(): |
|
218
|
|
|
""" |
|
219
|
|
|
Create user and admin roles |
|
220
|
|
|
""" |
|
221
|
|
|
with prefix('source {ENV_DIR}/bin/activate'.format(ENV_DIR=ENV_DIR)): |
|
222
|
|
|
with prefix('source {WWW_DIR}/server-config/host-export'.format(WWW_DIR=WWW_DIR)): |
|
223
|
|
|
with cd(WWW_DIR): |
|
224
|
|
|
sudo('python manage.py user create_role -n admin -d "Site Administrators"') |
|
225
|
|
|
sudo('python manage.py user create_role -n user -d Users') |
|
226
|
|
|
|
|
227
|
|
|
def setup_celery(): |
|
228
|
|
|
""" |
|
229
|
|
|
Upload configs for celery, make sure redis is running |
|
230
|
|
|
""" |
|
231
|
|
|
with cd('/home/www'): |
|
232
|
|
|
fabtools.files.upload_template( |
|
233
|
|
|
LOCAL_CONFIG_DIR + '/celery-start-gage', |
|
234
|
|
|
'.', |
|
235
|
|
|
use_sudo=True, |
|
236
|
|
|
use_jinja=True, |
|
237
|
|
|
user=USER, |
|
238
|
|
|
context={ |
|
239
|
|
|
'WWW_DIR': WWW_DIR, |
|
240
|
|
|
'ENV_DIR': ENV_DIR, |
|
241
|
|
|
'USER': USER, |
|
242
|
|
|
'GROUP': GROUP |
|
243
|
|
|
}, |
|
244
|
|
|
chown=True), |
|
245
|
|
|
sudo('chmod +x celery-start-gage') |
|
246
|
|
|
fabtools.files.upload_template( |
|
247
|
|
|
LOCAL_CONFIG_DIR + '/celery-start-beat-gage', |
|
248
|
|
|
'.', |
|
249
|
|
|
use_sudo=True, |
|
250
|
|
|
use_jinja=True, |
|
251
|
|
|
user=USER, |
|
252
|
|
|
context={ |
|
253
|
|
|
'WWW_DIR': WWW_DIR, |
|
254
|
|
|
'ENV_DIR': ENV_DIR, |
|
255
|
|
|
'USER': USER, |
|
256
|
|
|
'GROUP': GROUP |
|
257
|
|
|
}, |
|
258
|
|
|
chown=True), |
|
259
|
|
|
sudo('chmod +x celery-start-beat-gage') |
|
260
|
|
|
with cd('/etc/supervisor/conf.d/'): |
|
261
|
|
|
require.file('gage-web.conf', |
|
262
|
|
|
source=LOCAL_CONFIG_DIR+'/gage-web.conf', |
|
263
|
|
|
use_sudo=True) |
|
264
|
|
|
require.directory('/home/www/logs/gage-web/') |
|
265
|
|
|
sudo('supervisorctl reread') |
|
266
|
|
|
sudo('supervisorctl update') |
|
267
|
|
|
sudo('supervisorctl restart gage:*') |
|
268
|
|
|
|
|
269
|
|
|
|
|
270
|
|
|
def gage_restart(): |
|
271
|
|
|
""" |
|
272
|
|
|
Cron script to restart the supervisorctl gage:gage-celery-beat hourly |
|
273
|
|
|
""" |
|
274
|
|
|
fabtools.cron.add_task('restart-gage-beat', '@hourly', 'root', WWW_DIR+'/server-config/restart-gage.sh') |
|
275
|
|
|
|
|
276
|
|
|
|
|
277
|
|
|
|
|
278
|
|
|
def bootstrap(): |
|
279
|
|
|
""" |
|
280
|
|
|
Setup all the things |
|
281
|
|
|
""" |
|
282
|
|
|
create_user() |
|
283
|
|
|
create_www_folder() |
|
284
|
|
|
create_venv() |
|
285
|
|
|
install_system_requirements() |
|
286
|
|
|
# create_database() |
|
287
|
|
|
# configure_git() |
|
288
|
|
|
deploy() |
|
289
|
|
|
install_requirements() |
|
290
|
|
|
# Install ssl scripts |
|
291
|
|
|
install_config_files() |
|
292
|
|
|
upgrade_db_schema() |
|
293
|
|
|
create_roles() |
|
294
|
|
|
|