#! /usr/bin/python3
# coding=utf-8


import time
import paramiko
import MySQLdb
import json
from SetupMinersClass import SetupMiner


q1c = "SELECT REPLACE(hw_addr, ':','') as hw_addr, " \
      "serial, " \
      "net_num " \
      "FROM 1c_import " \
      "where imported = 0;"

qleases4 = "SELECT INET_NTOA(address) as ip4, " \
           "HEX(hwaddr)as hw_addr, hostname, " \
           "expire, " \
           "valid_lifetime " \
           "FROM lease4 " \
           "where INET_NTOA(address) like '10.{}.0%';"

qhosts_ip = "SELECT " \
         "INET_NTOA(ipv4_address) AS ipv4_address " \
         "FROM dhcp4.hosts;"

qinsert_hosts = "START TRANSACTION; " \
                "SET @ipv4_reservation='%s'; " \
                "SET @hostname = '%s'; " \
                "SET @identifier_type='hw-address'; " \
                "SET @identifier_value='%s'; " \
                "SET @dhcp4_subnet_id=1024; " \
                "INSERT INTO hosts ( dhcp_identifier, " \
                "  dhcp_identifier_type, " \
                "  dhcp4_subnet_id, " \
                "  ipv4_address, " \
                "  hostname) " \
                "VALUES ( " \
                "UNHEX(@identifier_value)," \
                "  (SELECT type FROM host_identifier_type WHERE name=@identifier_type)," \
                "  @dhcp4_subnet_id," \
                "  INET_ATON(@ipv4_reservation)," \
                "  @hostname); " \
                "COMMIT;"

qupdate_1c = "update 1c_import set imported = 1 where serial = '%s';"


def read_table(sql, dbhost, dbuser, dbpass, dbbase):
    try:
        conn = MySQLdb.connect(host=dbhost, user=dbuser,
                               passwd=dbpass, db=dbbase)
    except MySQLdb.Error as err:
        print("Connection error: {}".format(err))
        conn.close()
    try:
        cur = conn.cursor(MySQLdb.cursors.DictCursor)
        cur.execute(sql)
        data = cur.fetchall()
    except MySQLdb.Error as err:
        print("Query error: {}".format(err))
    conn.close()
    return data


def first_free_ip(ips, ip_pool, octet1, octet2, octet3):
    locked_ip = []
    octet4 = ''
    set_octets = False
    for ip in ips:
        octets = ip['ipv4_address'].split('.')
        if not set_octets:
            octet1 = octets[0]
            octet2 = octets[1]
            set_octets = True
        if octets[2] == str(octet3):
            locked_ip.append(octets[3])
    i = int(ip_pool[0])
    while i < int(ip_pool[1]):
        if not str(i) in locked_ip:
            octet4 = str(i)
            break
        i = i + 1
    if octet4 == '':
        return ''
    else:
        return "%s.%s.%s.%s" % (octet1, octet2, octet3, octet4)


def make_hosts(sql, ip, hostname, hw_addr, dbhost, dbuser, dbpass, dbbase):
    try:
        conn = MySQLdb.connect(host=dbhost, user=dbuser,
                               passwd=dbpass, db=dbbase)
    except MySQLdb.Error as err:
        print("Connection error: {}".format(err))
        conn.close()
    try:
        cur = conn.cursor(MySQLdb.cursors.DictCursor)
        cur.execute(sql % (ip, hostname, hw_addr))
        data = cur.fetchall()
        cur.close()
    except MySQLdb.Error as err:
        print("Query error: {}".format(err))
    try:
        cur = conn.cursor(MySQLdb.cursors.DictCursor)
        print(qupdate_1c % hostname)
        cur.execute(qupdate_1c % hostname)
        data = cur.fetchall()
        cur.close()
    except MySQLdb.Error as err:
        print("Query error: {}".format(err))
    conn.commit()
    conn.close()
    return data


def read_conf(file):
    with open(file) as f:
        conf = json.load(f)
    return conf


def main():
    conf = read_conf('config.json')
    sshs = read_conf('sshs.json')
    telnets = read_conf('telnets.json')
    print(sshs)
    print(telnets)
    telnets = read_conf('telnets.json')
    minerconf = {"sshuser": conf["sshuser"],
                 "sshpass": conf["sshpass"],
                 "sshport": conf["sshport"],
                 "telnetuser": conf["telnetuser"],
                 "telnetpass": conf["telnetpass"],
                 "telnetport": conf["telnetport"]}
    dbconf = [conf['dbhost'], conf['dbuser'], conf['dbpass'], conf['dbbase']]
    data_1c = read_table(q1c, *dbconf)
    data_leases = read_table(qleases4.format(conf['ip_oct2']), *dbconf)

    for line in data_1c:
        set_ip = first_free_ip(read_table(qhosts_ip, *dbconf),
                               conf['ippool'], conf['ip_oct1'], conf['ip_oct2'], line['net_num'])
        set_hw_addr = line['hw_addr']
        set_host = line['serial']
        make_hosts(qinsert_hosts, set_ip, set_host, set_hw_addr,
                   *dbconf)
        print('host built name %s, mac %s, ip %s' % (set_host, set_hw_addr, set_ip))
    for line in data_1c:
        for lease in data_leases:
            if line['hw_addr'] == lease['hw_addr']:
                print('rebooting %s' % lease['ip4'])
                SetupMiner(lease['ip4'], minerconf, telnets=telnets, sshs=sshs)


if __name__ == '__main__':
    main()