#!/bin/echo Usage: fab --list -f import contextlib import datetime from fabric.api import env, run, settings, sudo, prefix, cd, execute from fabric.context_managers import shell_env from fabric.decorators import roles, parallel env.roledefs['portal'] = ['localhost'] try: from vm.models import Node as _Node from storage.models import DataStore as _DataStore except Exception as e: print e else: env.roledefs['node'] = [unicode(n.host.ipv4) for n in _Node.objects.filter(enabled=True)] env.roledefs['storage'] = [_DataStore.objects.get().hostname] def update_all(): "Update and restart portal+manager, nodes and storage" execute(stop_portal) execute(parallel(update_node)) execute(update_storage) execute(update_portal) def pip(env, req): "Install pip requirements" with _workon(env): run("pip install -r %s" % req) @roles('portal') def migrate(): "Run db migrations" with _workon("circle"), cd("~/circle/circle"): run("./manage.py migrate") @roles('portal') def compile_js(): "Generate JS translation objects" with _workon("circle"), cd("~/circle/circle"): run("./manage.py compilejsi18n -o dashboard/static/jsi18n") @roles('portal') def collectstatic(): "Collect static files" with _workon("circle"), cd("~/circle/circle"): run("./manage.py collectstatic --noinput") @roles('portal') def compile_messages(): "Generate MO translation objects" with _workon("circle"), cd("~/circle/circle"): run("./manage.py compilemessages") @roles('portal') def compile_things(): "Compile translation and collect static files" compile_js() collectstatic() compile_messages() @roles('portal') def make_messages(): "Update PO translation templates and commit" with _workon("circle"), cd("~/circle/circle"): run("git status") run("./manage.py makemessages -d djangojs -a --ignore=jsi18n/*") run("./manage.py makemessages -d django -a") run("git commit -avm 'update PO templates'") @roles('portal') def test(test=""): "Run portal tests" with _workon("circle"), cd("~/circle/circle"): run("./manage.py test --settings=circle.settings.test %s" % test) def pull(dir="~/circle/circle"): "Pull from upstream branch (stash any changes)" now = unicode(datetime.datetime.now()) with cd(dir), shell_env(GIT_AUTHOR_NAME="fabric", GIT_AUTHOR_EMAIL="fabric@local", GIT_COMMITTER_NAME="fabric", GIT_COMMITTER_EMAIL="fabric@local"): run("git stash save update %s" % now) run("git pull --ff-only") @roles('portal') def update_portal(test=False): "Update and restart portal+manager" with _stopped("portal", "mancelery"): pull() pip("circle", "~/circle/requirements.txt") migrate() compile_things() if test: test() @roles('portal') def stop_portal(test=False): "Stop portal and manager" _stop_services("portal", "mancelery") @roles('node') def update_node(): "Update and restart nodes" with _stopped("node", "agentdriver"): pull("~/vmdriver") pip("vmdriver", "~/vmdriver/requirements/production.txt") pull("~/agentdriver") pip("agentdriver", "~/agentdriver/requirements.txt") @parallel @roles('storage') def update_storage(): "Update and restart storagedriver" with _stopped("storage"): pull("~/storagedriver") pip("storagedriver", "~/storagedriver/requirements/production.txt") @parallel @roles('node') def checkout(vmdriver="master", agent="master"): """Checkout specific branch on nodes""" with settings(warn_only=True), cd("~/vmdriver"): run("git checkout %s" % vmdriver) with settings(warn_only=True), cd("~/agentdriver"): run("git checkout %s" % agent) def _stop_services(*services): "Stop given services (warn only if not running)" with settings(warn_only=True): for service in reversed(services): sudo("stop %s" % service) def _start_services(*services): for service in services: sudo("start %s" % service) def _restart_service(*services): "Stop and start services" _stop_services(*services) _start_services(*services) @contextlib.contextmanager def _stopped(*services): _stop_services(*services) yield _start_services(*services) def _workon(name): return prefix("source ~/.virtualenvs/%s/bin/activate && " "source ~/.virtualenvs/%s/bin/postactivate" % (name, name))