#!/usr/bin/env python
#
#    reverseproxy-relation-changed - hook for when proxy relation changes
#
#    Copyright (C) 2011  Canonical Ltd.
#    Author: Clint Byrum <clint.byrum@canonical.com>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

import sys
import os
import subprocess
import tempfile

rebuild = os.path.basename(sys.argv[0]) == 'loadbalancer-rebuild'

pa = subprocess.Popen(["unit-get", "private-address"], stdout=subprocess.PIPE, 
    close_fds=True)
unit_address = pa.stdout.read().strip()

try:
    with open('.web-engine','r') as f:
        engine = f.readline().strip()
except IOError:
    engine = 'nginx'

if engine == 'apache2':
    conf_name = "loadbalancer"
    servers = """
<Proxy balancer://backend>
  BalancerMember http://127.0.0.1:8080/
"""
    server_line = "  BalancerMember http://%s:8080/\n"
    server_end = """
  ProxySet lbmethod=bybusyness
</Proxy>
"""
    t1 = '# Generated by juju'
    template = """
<VirtualHost *:80>

"""
    template += "  ServerName %s\n" % unit_address
    template += """
  ServerAlias *
  LogLevel warn
  ErrorLog ${APACHE_LOG_DIR}/wordpress-balancer-error.log
  ProxyPreserveHost On
  <Location />
    Order allow,deny
    Allow from all
    ProxyPass balancer://backend/
    ProxyPassReverse balancer://backend/
  </Location>
</VirtualHost>
"""
else:
    conf_name = "loadbalancer"
    servers = """
upstream backend {
  server 127.0.0.1:8080;
"""
    server_line = "  server %s:8080;\n"
    server_end = '}'

    t1 = """# Generated by juju
proxy_cache_path /mnt/ramdisk/proxy-cache levels=1:2 keys_zone=proxycache:5m max_size=1000m;
"""
    # servers will go here
    template = """
server {
  listen 80 default;
  server_name _;

  location / {
    set $no_cache "";

    if ($request_method !~ ^(GET|HEAD)$) {
      set $no_cache "1";
    }

    if ($no_cache = "1") {
      add_header Set-Cookie "_mcnc=1; Max-Age=30; Path=/";
      add_header X-Microcachable "0";
    }

    if ($http_cookie ~* "_mcnc") {
      set $no_cache "1";
    }

    proxy_no_cache $no_cache;
    proxy_cache_bypass $no_cache;

    proxy_redirect   http://backend  /;
    proxy_pass  http://backend;
    proxy_cache proxycache;
    proxy_cache_key $scheme$host$request_method$request_uri;
    proxy_cache_valid 200 60s;
    proxy_cache_use_stale updating;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-UA-Compatible "IE=Edge,chrome=1";

    proxy_max_temp_file_size 1M;
  }
}
"""

if rebuild:
    try:
        with open('.loadbalancer-units') as units:
            for paddress in units:
                servers += (server_line % (paddress.strip()))
    except IOError:
        pass
else:
    units = []
    p = subprocess.Popen("relation-list", stdout=subprocess.PIPE)
    for unit in p.stdout:
        units.append(unit.strip())

    print units

    lb_file = open('.loadbalancer-units', 'w')
    for unit in units:
        p = subprocess.Popen(["relation-get", "private-address", unit],
                             stdout=subprocess.PIPE, close_fds=True)
        paddress = p.stdout.read().strip()
        p.wait()
        lb_file.write("%s\n" % paddress)
        # Add all configured units:
        servers += (server_line % (paddress))

    lb_file.close()
servers += server_end

print servers

with tempfile.NamedTemporaryFile(dir="/etc/%s/sites-available/" % engine, 
        prefix='lb', delete=False) as conf:
    conf.write(t1 + servers + template)
    try:
        os.unlink("/etc/%s/sites-available/%s.old" % (engine, conf_name))
    except:
        pass
    try:
        os.rename("/etc/%s/sites-available/%s" % (engine, conf_name), 
            "/etc/%s/sites-available/%s.old" % (engine, conf_name))
    except:
        pass
    try:
        os.rename(conf.name, "/etc/%s/sites-available/%s" % (engine, conf_name))
    except:
        os.unlink(conf.name)

subprocess.call(["service", engine, "start"])
subprocess.check_call(["service", engine, "reload"])

subprocess.check_call(["open-port", "80"])
