FreedomBox/fabfile.py
Sunil Mohan Adapa defcb43883 Use json instead of simplejson library to avoid extra depedency
Simplejson is an externally mainainted version of json library available in
Python 2.6 and up. It supports Python 2.5 which were are not targetting.
It also boasts better speed which is not at all a factor for us.
2014-05-13 12:28:39 +05:30

236 lines
7.1 KiB
Python

#!/usr/bin/env python
# This is the fabric file I've been using to deploy things on my box
# and my freedombox.
#
# fab install should take you from base freedom-maker install to
# plinth box
import os,sys, subprocess
import json
import fabric.api
from fabric.api import local, env, cd, put, get, task
import cfg
fb_ip = "10.5.53.155"
BINDIR = "/usr/local/bin"
# defaults
env.user = 'root'
@task
def fb():
"Use this to set host to our freedombox (e.g.: fab fb deploy)"
env.hosts = [fb_ip]
@task
def all_hosts():
"Use this to set host to both localhost and freedombox"
env.hosts = ["localhost", "192.168.2.115"]
def remote_dir():
if env.host == fb_ip:
return "/usr/local/share/plinth"
else:
return "/home/james/src/plinth"
def run(*args, **kwargs):
if env.host == "localhost" or env.host=="127.0.0.1":
return local(*args, **kwargs)
else:
return fabric.api.run(*args, **kwargs)
def sudo(*args, **kwargs):
if env.host == "localhost" or env.host=="127.0.0.1":
return run("sudo %s" % args[0], *args[1:], **kwargs)
elif env.user == "root":
return run(*args, **kwargs)
else:
return fabric.api.sudo(*args, **kwargs)
@task
def get_remote_data_dir():
with cd(remote_dir()):
data_dir = run('python -c "import cfg; print cfg.data_dir"')
env.remote_data_dir = os.path.join(remote_dir(), data_dir)
sudo('mkdir -p %s' % env.remote_data_dir)
return env.remote_data_dir
@task
def move_data():
"Move install's data dir to where cfg specifies it should be"
get_remote_data_dir()
with cd(remote_dir()):
sudo('mv data %s' % os.path.split(env.remote_data_dir)[0])
@task
def make():
"Run the makefile, which generates docs and templates"
with cd(remote_dir()):
sudo('make')
def make_link_unless_exists(src, dest):
sudo('test -f %s || ln -s %s %s' % (dest, src, dest))
def link(src, dest):
sudo('ln -fs %s %s' % (src, dest))
@task
def santiago():
"Setup the Santiago port"
santiago_port = 52854
sudo('ifconfig lo up') # or else tor start fails
sudo('apt-get install -y --no-install-recommends tor curl ntp')
# tor needs accurate clock
sudo('date -s "%s"' % subprocess.check_output("date").rstrip())
# create tor hidden service dir
santiago_dir = os.path.join(get_remote_data_dir(), "santiago", "tor")
tor_dir = os.path.join(santiago_dir, "general")
sudo("mkdir -p " + tor_dir)
sudo("chown debian-tor:debian-tor " + tor_dir)
# ensure hidden service config is in torrc
local("rm -rf __fab__torrc")
get("/etc/tor/torrc", "__fab__torrc")
with open ("__fab__torrc", 'r') as INF:
rc = INF.read()
local("rm -rf __fab__torrc")
hidden_service_config = "HiddenServiceDir %s\nHiddenServicePort 80 127.0.0.1:%d" % (tor_dir, santiago_port)
if not hidden_service_config in rc:
sudo("echo '%s' >> /etc/tor/torrc" % hidden_service_config)
sudo('service tor restart')
def backslash_path(f):
if not f.startswith('/'):
f = os.path.abs(f)
if f == '/':
return ''
path, ret = os.path.split(f)
return backslash_path(path) + '\/' + ret
@task
def apache():
"configure apache to find reverse proxy for plinth"
sudo('apt-get install --no-install-recommends -y apache2 libapache2-mod-proxy-html apache2-utils openssl ssl-cert')
sudo('a2enmod proxy_http rewrite ssl')
sudo('touch /var/log/apache2/rewrite.log')
## ssl key and cert
ssl_target = "/etc/apache2/ssl/apache.pem"
sudo('mkdir -p %s' % os.path.split(ssl_target)[0])
sudo('test -f %s || echo "US\nNY\nNYC\nFBox\n\n\n" | openssl req -new -x509 -days 999 -nodes -out %s -keyout %s' % (ssl_target, ssl_target, ssl_target))
conf_path = os.path.join(remote_dir(), "share/apache2/plinth.conf")
sudo("mkdir -p " + os.path.split(conf_path)[0])
sudo("touch "+ conf_path)
sudo(r"sed -i 's/\(\s*\)DocumentRoot.*/\1DocumentRoot %s/g' %s" % (
backslash_path(os.path.join(remote_dir(), "static")),
conf_path))
link(conf_path, "/etc/apache2/sites-enabled/plinth.conf")
sslconf_path = os.path.join(remote_dir(), "share/apache2/plinth-ssl.conf")
sudo("mkdir -p " + os.path.split(sslconf_path)[0])
sudo("touch "+ sslconf_path)
sudo(r"sed -i 's/\(\s*\)DocumentRoot.*/\1DocumentRoot %s/g' %s" % (
backslash_path(os.path.join(remote_dir(), "static")),
sslconf_path))
link(sslconf_path, "/etc/apache2/sites-enabled/plinth-ssl.conf")
sudo('rm -f /etc/apache2/sites-enabled/000-default')
sudo('service apache2 restart')
@task
def deps():
"Basic plinth dependencies"
sudo('apt-get install --no-install-recommends -y python make pandoc python-pyme python-django python-bootstrapform libjs-twitter-bootstrap')
@task
def update():
"Copy modified git-tracked files from this branch to remote"
with cd(remote_dir()):
## Get .fab contents
sudo("touch .fab")
fab = run("cat .fab")
if not fab:
fab = {}
## Make list of files to put
try:
fab = json.loads(fab)
except:
fab={}
branch = [a[2:] for a in local("git branch", capture=True).split("\n") if a.startswith('*')][0]
files = local("git ls-tree -r --name-only %s" % branch, capture=True).split("\n")
else:
files = local("git diff --stat " + fab['last_update_from_commit'], capture=True).split("\n")[:-1]
files = [f.lstrip().split("|")[0].rstrip() for f in files]
## Put the files, one by one, respecting directories
dirs = {}
for pathspec in files:
d,fname = os.path.split(pathspec)
if not d in dirs.keys():
dirs[d]=[]
dirs[d].append(pathspec)
if dirs:
sudo('mkdir -p %s' % ' '.join([os.path.join(remote_dir(), d) for d in dirs.keys()]))
for d in dirs:
for f in dirs[d]:
if os.path.islink(f):
linked = local("ls -l %s" % f, capture=True).split("-> ")[1]
#link(os.path.join(remote_dir(), linked), os.path.join(remote_dir(), d, os.path.basename(f)))
put(f, os.path.join(remote_dir(), d),mirror_local_mode=True)
if f.endswith(".py"):
run("rm -f " + os.path.join(remote_dir(), d, os.path.basename)+"c")
## restart
make()
sudo('/etc/init.d/plinth restart')
## Record activity so we only put changed files next time
commit = local("git log -n 1", capture=True).split("\n")[0].split(" ")[1]
fab['last_update_from_commit'] = commit
with open(".fab", 'w') as OUTF:
OUTF.write(json.dumps(fab))
put(".fab", os.path.join(remote_dir(),".fab"))
local("rm -f .fab")
@task
def link_bin():
"Link executable and init.d script"
# todo: set daemon to point to currect binary
sudo('rm -rf ' + os.path.join(BINDIR, 'plinth.py'))
link(os.path.join(remote_dir(), "plinth.py"), os.path.join(BINDIR, 'plinth.py'))
sudo('rm -rf /etc/init.d/plinth')
link(os.path.join(remote_dir(), "share/init.d/plinth"), "/etc/init.d/plinth")
@task
def restart():
"Run plinth"
run('/etc/init.d/plinth restart')
@task
def stop():
"Stop plinth"
run('/etc/init.d/plinth stop')
@task
def proxy():
put("proxy_up.py", remote_dir())
@task
def deploy():
"Deploy plinth"
deps()
link_bin()
santiago()
update()
apache()