# -*- coding: utf-8 -*-
import sys , os, commands , glob, time, re
import logging
import mv_common
import socket, fcntl, struct, array
import netifaces, iplib
global etcnetdir
etcnetdir = "/etc/net/ifaces"

def setup_MYTH_DHCP(systemconfig):
    default_interface = systemconfig["default_interface"]
    try:
        defaultdhcp = systemconfig["HostUSEDHCP"+default_interface]
    except:
        logging.critical("    *Error occured finding default dhcp")
        defaultdhcp = "0"
    logging.debug("    Using %s as dhcp value for %s",  defaultdhcp, default_interface)
    return defaultdhcp

def all_interfaces():
    max_possible = 128  # arbitrary. raise if needed.
    bytes = max_possible * 32
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    names = array.array('B', '\0' * bytes)
    outbytes = struct.unpack('iL', fcntl.ioctl(
        s.fileno(),
        0x8912,  # SIOCGIFCONF
        struct.pack('iL', bytes, names.buffer_info()[0])
    ))[0]
    namestr = names.tostring()
    return [namestr[i:i+32].split('\0', 1)[0] for i in range(0, outbytes, 32)]

def get_ip(ifname):
    logging.debug("    Finding ip address for %s", ifname)
    all_if = all_interfaces()
    logging.debug("    found interfaces:%s", all_if)
    if ifname in all_if :
        logging.debug("    Found %s in all_interfaces", ifname)
    else:
        logging.critical("*     Couldn't find %s in list", ifname)
        ifname = all_if[0]
        logging.critical("*     Using %s for interface name", ifname)


    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])

def get_default_route(iface):
    rcroute = "127.0.0.1"
    f = open ('/proc/net/route', 'r')
    for line in f:
        words = string.split (line)
        netiface = words[0]
        route =  words[2]
        flags =  words[3]
        try:
            if ( netiface == iface ) and ( flags == "0003") :
                route = iplib.IPv4Address(route, notation="hex")
                t = str(route.get_dot())
                s = t.split(".")
                rcroute = s[3] + "." + s[2] + "." + s[1] + "." + s[0]
                break
        except ValueError:
            pass
    return rcroute

def setup_MYTH_IP(systemconfig):
    default_interface = systemconfig["default_interface"]
    #check for dhcp in use
    if setup_MYTH_DHCP(systemconfig) == "0":
        logging.debug("   dhcp is in use, finding dhcp ip")
        defaultip = get_ip(default_interface)
    else:
        try:
            defaultip = systemconfig["Hostip"+default_interface]
        except:
            logging.debug("    Error occured finding the defaultip")
            defaultip = "127.0.0.1"
    logging.debug("    Using %s as default ip", defaultip)
    return defaultip


def setup_MYTH_GW(systemconfig):
    default_interface = systemconfig["default_interface"]
    #check for dhcp in use
    if setup_MYTH_DHCP(systemconfig) == "0":
        logging.debug("   dhcp is in use, finding dhcp ip")
        defaultgw = get_default_route(default_interface)
    else:
        try:
            defaultgw = systemconfig["Hostgw"+default_interface]
        except:
            logging.debug("    Error occured finding the defaultgw")
            defaultgw = "127.0.0.1"
    logging.debug("    Using %s as default gw", defaultgw)
    return defaultgw


def setup_MTYH_DNS():
    returndns = "127.0.0.1"
    try:
      f = open ('/etc/resolv.conf', 'r')
      for line in f:
          if line.startswith("nameserver"):
              print line
              returndns = line.split()[1]
              break
    except:
      logging.debug("   Couldn't open /etc/resolv.conf for myth_dns")
    logging.debug("   using %s for myth_dns", returndns)
    return returndns





def flush(netdev):
    logging.debug("    Flushing %s",netdev)
    cmd = '''ip address flush dev %s''' %netdev
    mv_common.runcmd(cmd)

def kill_dhcp(basedir):
    logging.debug("    _Start of kill_dhcp")
    logging.debug("    Killing off dhcpd")
    stddir = os.getcwd()
    piddir = ("%s/var/run/") %basedir
    try:
        os.chdir(piddir)
        for FILE in glob.glob("dhcpcd-*.pid"):
            f = open(FILE,'r')
            pid = f.readline()
            f.close
            cmd = "kill -9 %s" %pid
            mv_common.runcmd(cmd)
            mv_common.remove_file(FILE)
        os.chdir(stddir)
    except:
        pass

def setup_nameserver(dns):
    logging.info("    Adding %s for DNS", dns)
    cmd = '''grep -q %s /etc/resolv.conf''' %dns
    status = mv_common.runcmd(cmd)
    if  not status == 0 :
        cmd =  ''' echo "nameserver %s" >> /etc/resolv.conf ''' %dns
        mv_common.runcmd(cmd)



def setup_hostname(systemconfig):
    logging.debug("   _Start of setup_hostname")
    try:
        hostname = systemconfig["hostname"]
    except:
        logging.critical("    *Hostname could not be set")
        logging.info("    Using default value of me")
        hostname = "diamonds"
    logging.info("    Setting the hostname to %s", hostname)
    cmd = ''' echo %s > /etc/hostname ''' %hostname
    mv_common.runcmd(cmd)
    cmd = "cat /etc/hosts | grep -v 127.0.0.1 | grep -v %s > /tmp/hosts" %hostname
    mv_common.runcmd(cmd)
    if systemconfig["mythdhcp"] == "1" :
        logging.debug("    not using dhcp")
        cmd = ''' echo 127.0.0.1 localhost  > /etc/hosts '''
        mv_common.runcmd(cmd)
        cmd = ''' echo %s %s  >> /etc/hosts ''' %(systemconfig["mythip"], systemconfig["hostname"])
        mv_common.runcmd(cmd)
    else:
        cmd = ''' echo 127.0.0.1 %s localhost  > /etc/hosts ''' %systemconfig["hostname"]
        mv_common.runcmd(cmd)
    cmd = '''cat /tmp/hosts >> /etc/hosts '''
    mv_common.runcmd(cmd)


def write_wpafile(line,netdev):
    logging.debug("    writing out wpa_supplicant.conf file")
    logging.debug(line)
    wpafile = etcnetdir+"/"+netdev+"/wpa_supplicant.conf"
    try:
        f = open(wpafile,'w')
        f.write(line)
        f.close()
    except:
        logging.debug("    Couldn't write to %s",wpafile)

def setup_wpa(netinfo,netdev):
    logging.info("    %s will use wpa for encryption",netdev)
    line = '''
#This file was automaticly generated, any changes may be lost
ctrl_interface=/var/run/wpa_supplicant
network={
    ssid="%s"
    # Preshared key as an ASCII passphrase
    psk="%s"
    scan_ssid=1
    key_mgmt=WPA-EAP WPA-PSK NONE
    pairwise=CCMP TKIP
    proto=WPA RSN
}''' %(netinfo["ESSID"],netinfo["KEY"])
    write_wpafile(line,netdev)

def setup_wep(netinfo,netdev):
    logging.info("    %s will use wep for encryption",netdev)
    logging.debug("    When a packet comes along, you must wep it")
    line='''
#This file was automaticly generated, any changes may be lost
ctrl_interface=/var/run/wpa_supplicant
network={
        ssid="%s"
        key_mgmt=NONE
        wep_key0=%s
        wep_tx_keyidx=0
        scan_ssid=1
        auth_alg=SHARED
}
''' %(netinfo["ESSID"],netinfo["KEY"])
    write_wpafile(line,netdev)


def setup_none(netinfo,netdev):
    logging.info("    %s will not use encryption",netdev)
    line = '''
#This file was automaticly generated, any changes may be lost
ctrl_interface=/var/run/wpa_supplicant
network={
        ssid="%s"
        key_mgmt=NONE
}
''' %netinfo["ESSID"]
    write_wpafile(line,netdev)

def setup_interface(netdev,systemconfig):
    logging.debug("    _Start of setup_interface for %s",netdev)
    nettrans = {'Hostip':'ip',
                'Hostnetmask':'netmask',
                'HostActive':'isactive',
                'HostDNS':'dns',
                'HostUSEDHCP':'UseDHCP',
                'HostGW':'GW',
                'HostMTU':'mtu',
                'HOST_iswireless':"wireless",
                'HostESSID':'ESSID',
                'HostKey':'KEY',
                'HostUseEncryption':'ENCRYPT'}
    netinfo = {}
    #populate the netinfo dict
    for netitem in nettrans:
        if systemconfig[netitem+netdev]:
            netinfo[nettrans[netitem]] = systemconfig[netitem+netdev]
        else:
            netinfo[nettrans[netitem]] = False
        logging.debug("     %s:%s",netitem,netinfo[nettrans[netitem]])
    logging.info("    %s wireless: %s", netdev,netinfo["wireless"])
    try:
        os.makedirs(etcnetdir)
    except:
        logging.debug("   Could not create %s",etcnetdir)

    optionfile=etcnetdir+"/"+netdev+"/options"
    if not os.path.exists(optionfile):
	try:
            os.makedirs(etcnetdir+"/"+netdev)
	except:
            pass
        mv_common.cp_and_log(systemconfig["TEMPLATES"]+"/etcnet/eth/options", optionfile)

    if netinfo["isactive"] == "1" :
        change_iface_state(netdev,"enabled")
    else:
        change_iface_state(netdev,"disabled")

    if netinfo["wireless"] == "1" :

        logging.info("    Enabling wireless extensions")
        cmd = ''' sed -i -e 's/^CONFIG_WIRELESS=.*$/CONFIG_WIRLESS=yes/g'  %s/%s/options''' %(etcnetdir,netdev)
        mv_common.runcmd(cmd)
        if netinfo["ENCRYPT"] == "WEP":
            setup_wep(netinfo,netdev)
        elif netinfo["ENCRYPT"] == "WPA":
            setup_wpa(netinfo,netdev)
        elif netinfo["ENCRYPT"] == "none":
            setup_none(netinfo,netdev)

    else:
        logging.info("    Disabling wireless extensions")
        cmd = '''sed -i -e 's/^CONFIG_WIRLESS=.*$/CONFIG_WIRLESS=no/g' %s/%s/options''' %(etcnetdir, netdev)
        mv_common.runcmd(cmd)
        #try:
        wpafile=etcnetdir+"/"+netdev+"/wpa_supplicant.conf"
            #os.remove(wpafile)
        mv_common.remove_file(wpafile)
        #except:
            #logging.debug("    Couldn't remove %s",wpafile)

    if netinfo["UseDHCP"] == "0" :
        logging.info("    Enabling DHCP support")
        cmd = ''' sed -i -e 's/^BOOTPROTO=.*$/BOOTPROTO=dhcp/g' %s/%s/options''' %(etcnetdir, netdev)
        mv_common.runcmd(cmd)
    else:
        logging.info("    Using static ip address of %s",netinfo["ip"])
        cmd = ''' sed -i -e 's/^BOOTPROTO=.*$/BOOTPROTO=static/g' %s/%s/options''' %(etcnetdir, netdev)
        mv_common.runcmd(cmd)
        cmd = '''echo "default via %s" > %s/%s/ipv4route''' %(netinfo["GW"], etcnetdir, netdev)
        mv_common.runcmd(cmd)
        cmd = '''echo "%s%s" > %s/%s/ipv4address ''' %(netinfo["ip"], netinfo["netmask"].split()[0], etcnetdir, netdev)
        mv_common.runcmd(cmd)
        setup_nameserver(netinfo["dns"])

    if netinfo["mtu"] :
        logging.info("    Setting mtu to %s", netinfo["mtu"])
        cmd = '''sed -i '/^mtu.*$/d' %s/%s/iplink''' %(etcnetdir,netdev)
        mv_common.runcmd(cmd)
        cmd = ''' echo "mtu %s" >> %s/%s/iplink''' %(netinfo["mtu"], etcnetdir,netdev)
        mv_common.runcmd(cmd)
    else:
        logging.info("    Using default mtu value")
        cmd = '''sed -i '/^mtu.*$/d' %s/%s/iplink''' %(etcnetdir,netdev)
        mv_common.runcmd(cmd)


def change_iface_state(netdev, state):
    if state == "enabled":
        logging.info("    Activating %s", netdev)
        cmd = '''sed -i -e 's/^ONBOOT=.*$/ONBOOT=yes/g' %s/%s/options''' %(etcnetdir,netdev)
        mv_common.runcmd(cmd)
        cmd = '''sed -i -e 's/^DISABLED=.*$/DISABLED=no/g' %s/%s/options ''' %(etcnetdir,netdev)
        mv_common.runcmd(cmd)
    else:
        logging.info("    Disabling %s", netdev)
        cmd = '''sed -i -e 's/^ONBOOT=.*$/ONBOOT=no/g' %s/%s/options''' %(etcnetdir,netdev)
        mv_common.runcmd(cmd)
        cmd = '''sed -i -e 's/^DISABLED=.*$/DISABLED=yes/g' %s/%s/options ''' %(etcnetdir,netdev)
        mv_common.runcmd(cmd)
        cmd = "/sbin/ifconfig %s down" %netdev
        mv_common.runcmd(cmd)
        cmd = "ip address flush %s" %netdev
        mv_common.runcmd(cmd)

def devcheck(netdev):
    cmd = ''' /sbin/ifconfig %s''' %netdev
    rc = mv_common.runcmd(cmd)
    if rc == 0 :
        return True
    else:
        return False

def udev_rules(netdev):
    filename = "/etc/udev/rules.d/net.rules"
    if devcheck(netdev):
        logging.info("    Finding macaddress for %s",netdev)
        try:
            macaddress = netifaces.ifaddresses(netdev)[netifaces.AF_LINK][0]['addr']
            logging.debug("    Macaddress: %s",macaddress)
        except:
            logging.debug("    Couldn't find mac address for %s",netdev)
            return
        try:
            f = open(filename,'a')
        except:
            logging.debug("    Couldn't open %s for writing", filename)
            return
        if netdev.startswith('eth'):
            line = '''KERNEL=="eth*", SYSFS{address}=="%s", NAME="%s"''' % ( macaddress , netdev)
        elif netdev.startswith('wlan'):
            line = '''KERNEL=="wlan*", SYSFS{address}=="%s", NAME="%s"'''% ( macaddress , netdev)
        elif netdev.startswith('ath'):
            line = '''KERNEL=="ath*", SYSFS{address}=="%s", NAME="%s"''' % ( macaddress , netdev)
        logging.debug("     adding to net.rules ")
        logging.debug("    %s",line)
        f.write(line)
        f.write("\n")
        f.close()

def find_active(systemconfig,this_is_install):
    interfacelist=('eth0', 'eth1', 'wlan0', 'wlan1', 'ath0')
    logging.debug("    _Start of find_active")

    if systemconfig["mythdhcp"] == "1":
        mv_common.remove_file("/etc/resolv.conf")
        cmd = ''' echo search lan > /etc/resolv.conf '''
        mv_common.runcmd(cmd)
        cmd = ''' echo nameserver 127.0.0.1 >> /etc/resolv.conf '''
        mv_common.runcmd(cmd)

    for netdev in interfacelist:
        if this_is_install:
            udev_rules(netdev)
        currentnet = "HostActive" + netdev
        try:
            systemconfig[currentnet]
        except:
            logging.debug("    %s is not defined",currentnet)
            change_iface_state(netdev, "disabled")
            continue
        if systemconfig[currentnet] == "1" :
            #check if device is present
            if devcheck(netdev) :
                setup_interface(netdev,systemconfig)
            else:
                logging.debug("    Interface %s not found in config", netdev)
                #change_iface_state(netdev, "disabled")
        else:
            change_iface_state(netdev, "disabled")

def vnc_netboot_check():
    logging.debug("    Start of VNC/NETBOOT check")
    vnc = False
    netboot = False
    try:
        f = open('/proc/cmdline', 'r')
        bootoptions = f.readlines()
        f.close()
    except:
        logging.critical("    *Couldn't open /proc/cmdline")
        logging.debug("    Assuming it's ok to fiddle with the network")
        return True
    bootoptions =  bootoptions[0]
    if re.match("vnc",bootoptions) != None :
        logging.debug("    Found VNC option")
        vnc = True
    if re.match("nfsroot",bootoptions) != None :
        logging.debug("    Found netboot option")
        netboot = True

    return (vnc or netboot)

def start_network():
    if not vnc_netboot_check():
        logging.info("    Restarting network")
        cmd ="/etc/net/scripts/network.init reload"
        mv_common.runcmd(cmd)
        cmd ="/etc/net/scripts/network.init restart"
        mv_common.runcmd(cmd)
    else:
        logging.info("    Will not restart network due to netboot/vnc")


def stop_network():
    if not vnc_netboot_check():
        logging.info("    Stopping network")
        cmd ="/etc/net/scripts/network.init stop"
        mv_common.runcmd(cmd)
        kill_dhcp("")
        interfacelist=('eth0', 'eth1', 'wlan0', 'wlan1', 'ath0')
        for i in interfacelist:
            flush(i)
    else:
        logging.info("    Will not stop network due to netboot/vnc")
    pass

def hostname_change_check(systemconfig):
    restartfe = False
    logging.debug("    _Start of hostname_change_check")
    oldhostname = socket.gethostname()
    #oldhostname = "crap"
    newhostname = systemconfig["hostname"]
    mv_root = systemconfig["MVROOT"]
    logging.debug("    Old hostname: %s", oldhostname)
    logging.debug("    New hostname: %s", newhostname)
    if oldhostname != newhostname :
        logging.info("    Changing hostname in database to match new hostname")
        cmd ="%s/bin/restore_default_settings.sh -cuhostname -o -h%s" %(mv_root, oldhostname)
        mv_common.runcmd(cmd)
        logging.info("    Changing hostname to %s", newhostname)
        cmd = "hostname %s" %newhostname
        mv_common.runcmd(cmd)
        if systemconfig["SystemType"] != "Frontend_only" :
            logging.info("    Restarting backend")
            mv_common.stop_service("mythbackend")
            mv_common.start_service("mythbackend")
            restartfe = True
    else:
        logging.debug("    old and new hostnames matched, leaving things along")
    logging.debug("  __End of hostname_change_check")
    return restartfe



def setup_network (systemconfig,this_is_install):
    if  mv_common.read_config(mv_common.module_config,"network")  == False  :
        logging.info("____Skipping of network, config disabled____")
        return False
    logging.info("____Start of network____")
    logging.info("    Setting up the network")
    restartfe = hostname_change_check(systemconfig)
    setup_hostname(systemconfig)
    find_active(systemconfig,this_is_install)
    start_network()
    logging.info("__End of network\n")
    return restartfe



##this is used by the install process to start the network
def install_network_setup(systemconfig):
    logging.info("____Start of network_install____")
    logging.info("    Setting up the network")
    #setup_MYTH_vars
    setup_hostname(systemconfig)
    stop_network()
    find_active(systemconfig)
    start_network()
    logging.info("__End of network install \n")