#! /usr/bin/env python
'''CGI that returns bconsole and bacula-fd configurations.

It can handle a couple parameters:
	hostname: if passed, the CGI will use this as the hostname to work
	with instead of using socket calls to determine the client
	hostname.

	bconsole: return a bconsole.conf instead of a bacula-fd.conf

	hash: return the hash of the config rather than the config itself

Install it someplace your clients will be able to hit, and grant it INSERT
and SELECT privileges in your configuration database.

You should also create a place for python to use for an egg cache, writable
only by your web server user, and ensure that PYTHON_EGG_CACHE points there.

'''
from __future__ import print_function

import cgi
import socket
import os
import sys
import re
import md5

os.environ.setdefault('PYTHON_EGG_CACHE', '/tmp')

# Only keep these two lines while doing development
import cgitb
cgitb.enable(display=0, logdir="/tmp")

import bacula_tools


def fix_hostname(hostname):
    '''Check for getting an IP address and, if so, turn it into a hostname'''
    if re.match(r'\d+\.\d+\.\d+\.\d+', hostname):
        result = socket.gethostbyaddr(hostname)
        if result:
            hostname = result[0]
    return hostname


def do_bconsole_config(bacula_config_object):
    '''Print out the bconsole configuration(s)'''
    result = []
    for x in bacula_tools.Console.Find(order_by='name'):
        result.append(str(x))
    for x in bacula_tools.Director.Find(order_by='name'):
        result.append(x.bconsole())
    return '\n'.join(result)


def find_client(bacula_config_object, guest, director):
    '''Will create the client if it wasn't found'''
    client = bacula_tools.Client(
        {bacula_tools.NAME: bacula_tools.hostname_mangler(guest)}).search()
    if not client[bacula_tools.ID]:
        # Didn't find the client, so create a new one!
        client.set(bacula_tools.ADDRESS, guest)
        bacula_tools.default_jobs(client)
        bacula_tools.default_director(client, director)

    return client


def main():
    '''Main entry point.'''
    # Ensure a valid HTTP response
    print('Content-type: text/plain; charset=iso-8859-1\r\n\r\n')

    query_variables = cgi.FieldStorage()
    bacula_config_object = bacula_tools.Bacula_Factory()
    hash = query_variables.getvalue('hash', False)
    result = ['''
# Host Config file generated by %s on %s.
#
#DO NOT EDIT THIS FILE BY HAND
''' % (sys.argv[0], os.uname()[1])]

    if 'bconsole' in os.environ.get('PATH_INFO', ''):
        result = do_bconsole_config(bacula_config_object)
    else:
        # This chooses, in order, passed-in hostname, REMOTE_HOST,
        # REMOTE_ADDR, localhost.localdomain
        # Obviously, the last value is a problem.
        hostname = query_variables.getvalue('hostname',
                                            os.environ.get('REMOTE_HOST',
                                                           os.environ.get('REMOTE_ADDR', 'localhost.localdomain')))
        guest = fix_hostname(hostname)
        client = find_client(bacula_config_object, guest,
                             query_variables.getvalue('director', ''))
        result.append(client.fd())
        for director_id in bacula_config_object.do_sql('SELECT director_id FROM pwords where obj_id = %s and obj_type = %s ORDER BY director_id', (client[bacula_tools.ID], client.IDTAG)):
            result.append(bacula_tools.Director(
                client_id=client[bacula_tools.ID]).search(director_id).fd())

        for messages_id in bacula_config_object.do_sql('SELECT messages_id FROM messages_link WHERE ref_id = %s AND link_type = %s', (client[bacula_tools.ID], client.IDTAG)):
            result.append(str(bacula_tools.Messages().search(messages_id)))

    # Convert result to a string.
    result = '\n'.join(result)
    if hash:
        print(md5.md5(result + '\n').hexdigest())
    else:
        print(result)


if __name__ == '__main__':
    main()
