#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 Red Hat, Inc.
#
# 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, version 2 of the License.
#
# 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.
import argparse
import logging
import sys

from ovirt_register.register import Register


def set_logger(logfile_path=None):
    """
    Set the logging schema
    """
    if logfile_path is not None:
        logging.basicConfig(
            filename=logfile_path,
            level=logging.DEBUG,
            format='%(name)s %(asctime)s %(message)s',
            datefmt='%m/%d/%Y %I:%M:%S %p'
        )
        return

    try:
        from systemd import journal
    except ImportError:
        # No systemd, logging into /var/log/messages
        from logging.handlers import SysLogHandler

    log = logging.getLogger()
    log.propagate = False
    log.setLevel(logging.DEBUG)

    try:
        formatter = logging.Formatter("%(name)s %(message)s")
        jhandler = journal.JournalHandler()
        jhandler.setLevel(logging.DEBUG)
        jhandler.setFormatter(formatter)
        log.addHandler(jhandler)
    except UnboundLocalError:
        try:
            syslog = SysLogHandler(address="/dev/log")
            formatter = logging.Formatter("%(name)s %(asctime)s %(message)s")
            syslog.setFormatter(formatter)
            log.addHandler(syslog)
        except Exception as e:
            print("WARNING:")
            print("========")
            print(("Cannot set log handler: /dev/log, to save logging "
                  "use --log option!\n{0}\n".format(e)))


def main():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawTextHelpFormatter,
        description='Tool to register node to Engine',
        epilog='Example of use:\n%(prog)s '
                    '--engine-fqdn engine.mydomain'
    )

    parser.add_argument(
        '--engine-fqdn',
        help="Engine FQDN (See also: --check-fqdn)",
        required=True
    )

    parser.add_argument(
        '--engine-https-port',
        help="Define engine https port."
             " If not provided, will be used 443",
    )

    parser.add_argument(
        '--node-fqdn',
        help="Node FQDN or address",
    )

    parser.add_argument(
        '--node-name',
        help="Define a node name",
    )

    parser.add_argument(
        '--ssh-user',
        help="SSH username to establish the connection with Engine. "
             "If not provided, the user which is "
             "executing the script will catch and used",
    )

    parser.add_argument(
        '--ssh-port',
        help="SSH port to establish the connection with Engine "
             "If not provided, the script will use the default "
             "SSH port 22"
    )

    parser.add_argument(
        '--nocheck-fqdn',
        default=True,
        action='store_false',
        help="Disable FQDN check for Engine CA, this option "
             "is enabled by default",
    )

    parser.add_argument(
        '--fingerprint',
        help="Specify an existing fingerprint to be validated against "
             "Engine CA fingerprint",
    )

    parser.add_argument(
        '--log',
        help="Specify a file to redirect the log",
    )

    parser.add_argument(
        '--cafile',
        help="Specify the full path for the CA file, it will be created"
             " if doesn't exist."
    )

    parser.add_argument(
        '--vdsm-port',
        help="The port to be used in the communication between the "
             "node agent and Engine, if not provided will be used "
             "the default port 54321"
    )

    parser.add_argument(
        '--force-uuid',
        help="Force the UUID of machine. It's useful for machines "
             "that provides duplicate UUID."
    )

    parser.add_argument(
        '--nopersist-uuid',
        default=False,
        action='store_true',
        help="Do not save the UUID in the disk (/etc/vdsm/vdsm.id)."
             "The default behaviour is save into the disk (Use: True or False)"
    )
    args = parser.parse_args()

    set_logger(args.log)
    reg = Register(engine_fqdn=args.engine_fqdn,
                   engine_https_port=args.engine_https_port,
                   node_fqdn=args.node_fqdn,
                   node_name=args.node_name,
                   ssh_user=args.ssh_user,
                   ssh_port=args.ssh_port,
                   fingerprint=args.fingerprint,
                   vdsm_port=args.vdsm_port,
                   ca_file=args.cafile,
                   check_fqdn=args.nocheck_fqdn)

    try:
        reg.detect_reg_protocol()

        uuid = reg.collect_host_uuid(force_uuid=args.force_uuid,
                                     nopersist_uuid=args.nopersist_uuid)

        reg.pki_trust()
        ssh_trust = reg.ssh_trust()
        reg.execute_registration()
    except Exception as e:
        reg.logger.exception("Exception: {exp}".format(exp=e))
        raise RuntimeError("Cannot register this host "
                           "into {e}:\n {exc}".format(e=args.engine_fqdn,
                                                      exc=e))

    print("Registration protocol detected:")
    print("============================")
    print(("\t{0}\n".format(reg.get_registration_protocol())))

    print("Host UUID:")
    print("============================")
    print(("\t{0}\n".format(uuid)))

    print("PEM file data:")
    print("============================")
    print(("\t{0}\n".format(reg.get_pem_data())))

    print("Fingerprint:")
    print("============================")
    print(("\t{0}\n".format(reg.get_pem_fingerprint())))

    print("Authorized keys file:")
    print("============================")
    print(("\t{0}\n".format(ssh_trust)))

    print(("Registration completed, host is pending approval "
          "on Engine: {e}".format(e=args.engine_fqdn)))

    reg.logger.debug("Registration successfully triggered!")

    return 0

if __name__ == '__main__':
    sys.exit(main())
