#!/usr/bin/python

import sys, Tartarus, Ice, krb5user, traceback
import Tartarus.system
from Tartarus.system import consdialog, config, hosts, Error
from Tartarus.deploy import client, save_keys
from Tartarus.iface import core, Kerberos

class Communicator:
    __communicator = None
    @classmethod
    def get(cls):
        if cls.__communicator is None:
            idata = Ice.InitializationData()
            idata.properties = Ice.createProperties()
            idata.properties.load('/etc/Tartarus/clients/all.config')
            cls.__communicator = Ice.initialize(None, idata)
        return cls.__communicator
    @classmethod
    def propertyToProxy(cls, property_name):
        return cls.get().propertyToProxy(property_name)


_template_dir = '/usr/share/Tartarus/templates/'
_krb5_conf_template = _template_dir + "clients/krb5.conf.template"
_ice_config_template = _template_dir + "all/all.config.template"

def deploy(opts):
    Tartarus.system.check.check_krb5_lookup(opts['domain'])
    config.gen_config_from_file('/etc/krb5.conf',
                                _krb5_conf_template, opts, True)

    hosts.replace_localhost(opts['fqdn'])
    krb5user.kinitPasswordPromptPosix(
            consdialog.ask('user[admin]: ', 'sysadmin'))

    client.deploy_client_start(opts)

    spn = 'host/%s' % opts['fqdn']
    krb5prx = Communicator.propertyToProxy('Tartarus.Kerberos.KadminPrx')
    kadmin = Kerberos.KadminPrx.checkedCast(krb5prx)
    try:
        spr = kadmin.createServicePrincipal('host', opts['fqdn'])
    except core.AlreadyExistsError:
        spr = kadmin.getPrincKeys(spn)
    save_keys(spr)

    if consdialog.yesno("Do you want to register this computer "
                        "in Tartarus DNS now?"):
        auto_dns_update = consdialog.yesno(
                "Do you want to run DNS updater automatically "
                "every time this system starts (helpfull when "
                "address is obtained from DHCP pool)?")
        client.deploy_client_dnsupdate(opts, auto_dns_update)

    client.deploy_client_finish(opts)



def get_checked_fqdn(domain, hostname):
    fqdn = hostname
    if not '.' in fqdn:
        fqdn += '.'
        fqdn += domain
    if not fqdn.endswith(domain):
        raise Error('Wrong domain "%s" for fqdn "%s"' % (domain, fqdn))
    return fqdn


def _main():
    fqdn_list = []
    if len(sys.argv) > 1:
        fqdn_list.append(sys.argv[1])

    domain = Tartarus.system.hostname.getdomain()
    fqdn = get_checked_fqdn(domain, Tartarus.system.hostname.getfqdn())
    fqdn_list.append(fqdn)

    localhosts = hosts.get_localhosts()
    for record in localhosts:
        for h in record.split():
            if not h.startswith('localhost') and h.find('.') > 0:
                fqdn_list.append(h) 

    user_fqdn = consdialog.choice(
            'Enter Full Qualified Domain Name (FQDN) of your host', fqdn_list)
    if user_fqdn != fqdn:
        domain = Tartarus.system.hostname.getdomain(user_fqdn)
        fqdn = get_checked_fqdn(domain, user_fqdn)
        Tartarus.system.hostname.sethostname(fqdn)

    deploy({ 'domain' : domain, 'fqdn' : fqdn })


def _format_exception():
    et, ev, _  = sys.exc_info()

    if et is Ice.InitializationException:
        code = -1
        msg = "Failed to initialize runtime: %s" % ev.reason
    elif et is OSError:
        code =  ev.errno
        msg = "OS Error: %s" % ev.strerror
    else:
        code =  -1
        msg = str().join(traceback. format_exception(et, ev, None))

    if not msg.endswith('\n'):
        msg += '\n'

    return (code, msg)

def main():
    try:
        _main()
        sys.exit(0)
    except KeyboardInterrupt:
        msg = "\n\nJoin canceled!\n"
        code = -1
    except Exception:
        code, msg = _format_exception()
    sys.stderr.write(msg)
    sys.exit(code)


if __name__ == '__main__':
    main()

