2 """ Karmaworld Fabric management script
3 Finals Club (c) 2013"""
8 from fabric.api import cd, env, lcd, prefix, run, sudo, task, local, settings
9 from fabric.contrib import files
12 env.group = 'www-data'
13 env.proj_repo = 'git@github.com:FinalsClub/karmaworld.git'
14 env.repo_root = '~/karmaworld' # transient setting for VMs only
15 env.proj_root = '/var/www/karmaworld'
16 env.branch = 'prod' # only used for supervisor conf two lines below. cleanup?
17 env.code_root = env.proj_root
18 env.supervisor_conf = '{0}/confs/{1}/supervisord.conf'.format(env.code_root, env.branch)
19 env.usde_csv = '{0}/confs/acceditation.csv'.format(env.code_root)
21 env.use_ssh_config = True
23 ######## Run Commands in Virtual Environment
26 Find and memoize the virtualenv for use internally.
28 default_venv = env.proj_root + '/venv/bin/activate'
30 # Return environment root if its been memoized
31 if 'env_root' in env and env['env_root']:
32 return env['env_root']
34 # Not memoized. Try to find a single unique virtual environment.
35 outp = run("find -L {0} -path '*/bin/activate' | grep -v '/local/'".format(env.proj_root))
36 if not len(outp) or len(outp.splitlines()) != 1:
37 # Cannot find any virtualenv or found multiple virtualenvs.
38 if len(outp) and default_venv not in outp:
39 # Multiple venvs and the default is not present.
40 raise Exception('Cannot determine the appropriate virtualenv.')
41 # If there are no virtualenvs, then use the default (this will create
42 # one if being called by make_virtualenv, otherwise it will cause an
44 # If there are multiple virtualenvs and the default is in their midst,
47 # Pop off the /bin/activate from /venv/bin/activate
48 outp = os.path.sep.join(outp.split(os.path.sep)[:-2])
49 env['env_root'] = outp
52 def virtenv_exec(command):
54 Execute command in Virtualenv
56 with prefix('source {0}/bin/activate'.format(virtenv_path())):
59 ######## Sync database
65 virtenv_exec('{0}/manage.py syncdb --migrate'.format(env.code_root))
68 ####### Collect Static Files
72 Collect static files (if AWS config. present, push to S3)
75 virtenv_exec('%s/manage.py collectstatic --noinput' % env.code_root )
77 ####### Run Dev Server
81 Runs the built-in django webserver
84 virtenv_exec('%s/manage.py runserver' % env.code_root)
86 ####### Create Virtual Environment
91 Link the karmaworld repo into the appropriate production location
93 if not files.exists(env.code_root):
94 run('ln -s {0} {1}'.format(env.repo_root, env.code_root))
97 def make_virtualenv():
101 run('virtualenv {0}'.format(virtenv_path()))
104 def start_supervisord():
108 virtenv_exec('supervisord -c {0}'.format(env.supervisor_conf))
112 def stop_supervisord():
116 virtenv_exec('supervisorctl -c {0} shutdown'.format(env.supervisor_conf))
120 def restart_supervisord():
122 Restarts supervisord, also making sure to load in new config data.
124 virtenv_exec('supervisorctl -c {0} update; supervisorctl -c {0} restart all
125 '.format(env.supervisor_conf))
128 def supervisorctl(action, process):
130 Takes as arguments the name of the process as is
131 defined in supervisord.conf and the action that should
132 be performed on it: start|stop|restart.
134 virtenv_exec('supervisorctl -c {0} {1} {2}'.format(env.supervisor_conf, action, process))
140 Starts the celeryd process
142 supervisorctl('start', 'celeryd')
148 Stops the celeryd process
150 supervisorctl('stop', 'celeryd')
154 def restart_celery():
156 Restarts the celeryd process
158 supervisorctl('restart', 'celeryd')
162 def start_gunicorn():
164 Starts the gunicorn process
166 supervisorctl('start', 'gunicorn')
172 Stops the gunicorn process
174 supervisorctl('stop', 'gunicorn')
178 def restart_gunicorn():
180 Restarts the gunicorn process
182 supervisorctl('restart', 'gunicorn')
185 ####### Update Requirements
188 virtenv_exec('pip install -r {0}/reqs/prod.txt'.format(env.code_root))
190 ####### Pull new code
193 virtenv_exec('cd %s; git pull' % env.proj_root )
197 Create backup using bup
204 Deploy expected files and directories from non-apt system services.
206 ini_parser = ConfigParser.SafeConfigParser()
207 if not ini_parser.read(env.supervisor_conf):
208 raise Exception("Could not parse INI file {0}".format(env.supervisor_conf))
209 for section, option in (('supervisord','logfile'),
210 ('supervisord','pidfile'),
211 ('unix_http_server','file'),
212 ('program:celeryd','stdout_logfile')):
213 filepath = ini_parser.get(section, option)
214 # generate file's directory structure if needed
215 run('mkdir -p {0}'.format(os.path.split(filepath)[0]))
216 # touch a file and change ownership if needed
217 if 'log' in option and not files.exists(filepath):
218 sudo('touch {0}'.format(filepath))
219 sudo('chown {0}:{1} {2}'.format(env.local_user, env.group, filepath))
224 Ensure secret files exist for syncdb to run.
227 secrets_path = env.code_root + '/karmaworld/secret'
228 secrets_files = ('filepicker.py', 'static_s3.py', 'db_settings.py', 'drive.py', 'client_secrets.json', 'drive.p12')
231 for sfile in secrets_files:
232 ffile = os.path.sep.join((secrets_path,sfile))
233 if not files.exists(ffile):
234 errors.append('{0} missing. Please add and try again.'.format(ffile))
236 raise Exception('\n'.join(errors))
241 Download USDE accreditation school CSV.
243 virtenv_exec('{0}/manage.py fetch_usde_csv {1}'.format(env.code_root, env.usde_csv))
248 Import accreditation school CSV into the database and scrub it.
250 virtenv_exec('{0}/manage.py import_usde_csv {1}'.format(env.code_root, env.usde_csv))
251 virtenv_exec('{0}/manage.py sanitize_usde_schools'.format(env.code_root))
254 def install_pdf2htmlEX():
256 # Some things we need:
257 sudo apt-get install cmake libpng-dev libjpeg-dev libgtk2.0-dev pkg-config libfontconfig1-dev autoconf libtool
259 # Ubuntu 12.04 comes with a version of poppler that is too
260 # old, so compile our own
261 wget http://poppler.freedesktop.org/poppler-0.24.4.tar.xz
262 tar xf poppler-0.24.4.tar.gz
263 ./configure --prefix=/usr --enable-xpdf-headers
267 # Ubuntu 12.04 comes with a version of fontforge that is too
268 # old, so compile our own
269 git clone https://github.com/fontforge/fontforge.git
271 ./configure --prefix=/usr
276 wget https://github.com/coolwanglu/pdf2htmlEX/archive/v0.10.tar.gz
283 print "not implemented yet!"
288 Sets up and deploys the project for the first time.
305 Deploys the latest changes
311 restart_supervisord()
312 ########## END COMMANDS