# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
# 
#   http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
from .utilities import bash
from .cloudException import CloudRuntimeException, CloudInternalException
import logging
import os
import re
import subprocess

class networkConfig:
    class devInfo:
        def __init__(self, macAddr, ipAddr, netmask, gateway, type, name):
            self.name = name
            self.macAdrr = macAddr
            self.ipAddr = ipAddr
            self.netmask = netmask
            self.gateway = gateway
            self.type = type
            self.name = name
            #dhcp or static
            self.method = None 
     
    @staticmethod
    def listNetworks():
        devs = os.listdir("/sys/class/net/") 
        devs = list(filter(networkConfig.isBridge, devs)) 
        return devs
    @staticmethod
    def getDefaultNetwork():
        cmd = bash("route -n|awk \'/^0.0.0.0/ {print $2,$8}\'") 
        if not cmd.isSuccess():
            logging.debug("Failed to get default route")
            raise CloudRuntimeException("Failed to get default route")

        result = cmd.getStdout().split(" ")
        gateway = result[0]
        dev = result[1]

        pdi = networkConfig.getDevInfo(dev)
        logging.debug("Found default network device:%s"%pdi.name)
        pdi.gateway = gateway
        return pdi

    @staticmethod
    def createBridge(dev, brName):
        if not networkConfig.isBridgeSupported():
            logging.debug("bridge is not supported")
            return False
        if networkConfig.isBridgeEnslavedWithDevices(brName):
            logging.debug("bridge: %s has devices enslaved"%brName)
            return False

        cmds = ""
        if not networkConfig.isBridge(brName):
            cmds = "ip link add name %s type bridge ;"%brName
    
        cmds += "ifconfig %s up;"%brName
        cmds += "ip link set dev %s master %s"%(dev, brName)
        return bash(cmds).isSuccess()

    @staticmethod
    def isBridgeEnslavedWithDevices(brName):
        if not networkConfig.isBridge(brName):
            return False        

        if not os.listdir("/sys/class/net/%s/brif"%brName):
            return False           

        return True

    @staticmethod
    def isBridgeSupported():
        if os.path.exists("/proc/sys/net/bridge"):
            return True

        return bash("modprobe -b bridge").isSuccess()

    @staticmethod
    def isNetworkDev(devName):
        return os.path.exists("/sys/class/net/%s" % devName)

    @staticmethod
    def isBridgePort(devName):
        return os.path.exists("/sys/class/net/%s/brport" % devName)
    
    @staticmethod
    def isBridge(devName):
        return os.path.exists("/sys/class/net/%s/bridge" % devName)

    @staticmethod
    def isOvsBridge(devName):
        cmd = bash("which ovs-vsctl")
        if not cmd.isSuccess():
            return False
        try:
            return 0==subprocess.check_call(("ovs-vsctl", "br-exists", devName))
        except subprocess.CalledProcessError:
            return False

    @staticmethod
    def getBridge(devName):
        bridgeName = None
        if os.path.exists("/sys/class/net/%s/brport/bridge"%devName):
            realPath = os.path.realpath("/sys/class/net/%s/brport/bridge"%devName)
            bridgeName = realPath.split("/")[-1] 
        return bridgeName

    @staticmethod
    def getEnslavedDev(br, brPort):
        if not networkConfig.isBridgeEnslavedWithDevices(br):
            return None

        for dev in os.listdir("/sys/class/net/%s/brif"%br):
            br_port = int(open("/sys/class/net/%s/brif/%s/port_no"%(br,dev)).readline().strip("\n"), 16)
            if br_port == brPort:
                return dev

        return None
        
    @staticmethod
    def getDevInfo(dev):
        if not networkConfig.isNetworkDev(dev):
            logging.debug("dev: " + dev + " is not a network device")
            raise CloudInternalException("dev: " + dev + " is not a network device")

        netmask = None
        ipAddr = None
        macAddr = None

        cmd = bash("ifconfig " + dev)
        if not cmd.isSuccess():
            logging.debug("Failed to get address from ifconfig")
            raise CloudInternalException("Failed to get network info by ifconfig %s"%dev)

        for line in cmd.getLines():
            if line.find("HWaddr") != -1:
                macAddr = line.split("HWaddr ")[1].strip(" ")
            elif line.find("inet ") != -1:
                m = re.search("addr:(.*)\ *Bcast:(.*)\ *Mask:(.*)", line)
                if m is not None:
                    ipAddr = m.group(1).rstrip(" ")
                    netmask = m.group(3).rstrip(" ")

        if networkConfig.isBridgePort(dev):
            type = "brport"
        elif networkConfig.isBridge(dev) or networkConfig.isOvsBridge(dev):
            type = "bridge"
        else:
            type = "dev"

        return networkConfig.devInfo(macAddr, ipAddr, netmask, None, type, dev)

