#!/usr/bin/python

"""
Libraries for creating L3 topologies with routing protocols.
"""

from mininet.node import Host, OVSBridge
from mininet.nodelib import NAT
from mininet.log import info, debug, error
from mininet.cli import CLI
from ipaddress import ip_network, ip_address, ip_interface
import os

class RoutedHost(Host):
    """Host that can be configured with multiple IP addresses."""
    def __init__(self, name, ips, gateway, *args, **kwargs):
        super(RoutedHost, self).__init__(name, *args, **kwargs)

        self.ips = ips
        self.gateway = gateway

    def config(self, **kwargs):
        Host.config(self, **kwargs)

        self.cmd('ip -4 addr flush dev %s' % self.defaultIntf())
        for ip in self.ips:
            self.cmd('ip addr add %s dev %s' % (ip, self.defaultIntf()))

        self.cmd('ip route add default via %s' % self.gateway)

class RoutedHost6(Host):
    """Host that can be configured with multiple IP addresses."""
    def __init__(self, name, ips, gateway, *args, **kwargs):
        super(RoutedHost6, self).__init__(name, *args, **kwargs)

        self.ips = ips
        self.gateway = gateway

    def config(self, **kwargs):
        Host.config(self, **kwargs)

        self.cmd('ip -6 addr flush dev %s' % self.defaultIntf())
        for ip in self.ips:
            self.cmd('ip -6 addr add %s dev %s' % (ip, self.defaultIntf()))

        self.cmd('ip -6 route add default via %s' % self.gateway)

class Router(Host):

    """An L3 router.
    Configures the Linux kernel for L3 forwarding and supports rich interface
    configuration of IP addresses, MAC addresses and VLANs."""

    def __init__(self, name, interfaces, *args, **kwargs):
        super(Router, self).__init__(name, **kwargs)

        self.interfaces = interfaces

    def config(self, **kwargs):
        super(Host, self).config(**kwargs)

        self.cmd('sysctl net.ipv4.ip_forward=1')
        self.cmd('sysctl net.ipv4.conf.all.rp_filter=0')
        self.cmd('sysctl net.ipv6.conf.all.forwarding=1')

        for intf, configs in self.interfaces.items():
            self.cmd('ip -4 addr flush dev %s' % intf)
            self.cmd( 'sysctl net.ipv4.conf.%s.rp_filter=0' % intf )

            if not isinstance(configs, list):
                configs = [configs]

            for attrs in configs:
                # Configure the vlan if there is one
                if 'vlan' in attrs:
                    vlanName = '%s.%s' % (intf, attrs['vlan'])
                    self.cmd('ip link add link %s name %s type vlan id %s' %
                             (intf, vlanName, attrs['vlan']))
                    self.cmd('ip link set %s up' % vlanName)
                    addrIntf = vlanName
                else:
                    addrIntf = intf

                # Now configure the addresses on the vlan/native interface
                if 'mac' in attrs:
                    self.cmd('ip link set %s down' % addrIntf)
                    self.cmd('ip link set %s address %s' % (addrIntf, attrs['mac']))
                    self.cmd('ip link set %s up' % addrIntf)
                for addr in attrs['ipAddrs']:
                    self.cmd('ip addr add %s dev %s' % (addr, addrIntf))

class QuaggaRouter(Router):

    """Runs Quagga to create a router that can speak routing protocols."""

    binDir = '/usr/lib/quagga'
    logDir = '/var/log/quagga'

    def __init__(self, name, interfaces,
                 defaultRoute=None,
                 zebraConfFile=None,
                 protocols= [],
                 fpm=None,
                 runDir='/var/run/quagga', *args, **kwargs):
        super(QuaggaRouter, self).__init__(name, interfaces, **kwargs)

        self.protocols = protocols
        self.fpm = fpm

        for p in self.protocols:
            p.setQuaggaRouter(self)

        self.runDir = runDir
        self.defaultRoute = defaultRoute

        # Ensure required directories exist
        try:
            original_umask = os.umask(0)
            if (not os.path.isdir(QuaggaRouter.logDir)):
                os.makedirs(QuaggaRouter.logDir, 0777)
            if (not os.path.isdir(self.runDir)):
                os.makedirs(self.runDir, 0777)
        finally:
            os.umask(original_umask)

        self.zebraConfFile = zebraConfFile
        if (self.zebraConfFile is None):
            self.zebraConfFile = '%s/zebrad%s.conf' % (self.runDir, self.name)
            self.generateZebra()

        self.socket = '%s/zebra%s.api' % (self.runDir, self.name)

        self.zebraPidFile = '%s/zebra%s.pid' % (self.runDir, self.name)

    def generateZebra(self):
        configFile = open(self.zebraConfFile, 'w+')
        configFile.write('log file %s/zebrad%s.log\n' % (QuaggaRouter.logDir, self.name))
        configFile.write('hostname zebra-%s\n' % self.name)
        configFile.write('password %s\n' % 'quagga')
        if (self.fpm is not None):
            configFile.write('fpm connection ip %s port 2620' % self.fpm)
        configFile.close()

    def config(self, **kwargs):
        super(QuaggaRouter, self).config(**kwargs)

        self.cmd('%s/zebra -d -f %s -z %s -i %s'
                 % (QuaggaRouter.binDir, self.zebraConfFile, self.socket, self.zebraPidFile))
        print("\n")
        print('%s/zebra -d -f %s -z %s -i %s'
                 % (QuaggaRouter.binDir, self.zebraConfFile, self.socket, self.zebraPidFile))

        for p in self.protocols:
            p.config(**kwargs)

        if self.defaultRoute:
            self.cmd('ip route add default via %s' % self.defaultRoute)

    def stopProtocols(self, **kwargs):
        for p in self.protocols:
            p.stop(**kwargs)

    def startProtocols(self, **kwargs):
        for p in self.protocols:
            p.start(**kwargs)

    def terminate(self, **kwargs):
        self.cmd("ps ax | grep '%s' | awk '{print $1}' | xargs kill"
                 % (self.socket))

        for p in self.protocols:
            p.terminate(**kwargs)

        super(QuaggaRouter, self).terminate()

class Protocol(object):

    """Base abstraction of a protocol that the QuaggaRouter can run."""

    def setQuaggaRouter(self, qr):
        self.qr = qr

    def config(self, **kwargs):
        pass

    def stop(self, **kwargs):
        pass

    def start(self, **kwargs):
        pass

    def terminate(self, **kwargs):
        pass

class BgpProtocol(Protocol):

    """Configures and runs the BGP protocol in Quagga."""

    def __init__(self, configFile=None, asNum=None, neighbors=[], routes=[], *args, **kwargs):
        self.configFile = configFile

        self.asNum = asNum
        self.neighbors = neighbors
        self.routes = routes

    def config(self, **kwargs):
        if self.configFile is None:
            self.configFile = '%s/bgpd%s.conf' % (self.qr.runDir, self.qr.name)
            self.generateConfig()

        bgpdPidFile = '%s/bgpd%s.pid' % (self.qr.runDir, self.qr.name)

        self.qr.cmd('%s/bgpd -d -f %s -z %s -i %s'
                     % (QuaggaRouter.binDir, self.configFile, self.qr.socket, bgpdPidFile))

    def stop(self, **kwargs):
        self.qr.cmd('pkill -f %s' % self.configFile)

    def start(self, **kwargs):
        bgpdPidFile = '%s/bgpd%s.pid' % (self.qr.runDir, self.qr.name)
        self.qr.cmd('%s/bgpd -d -f %s -z %s -i %s'
                     % (QuaggaRouter.binDir, self.configFile, self.qr.socket, bgpdPidFile))

    def generateConfig(self):
        conf = ConfigurationWriter(self.configFile)

        def getRouterId(interfaces):
            intfAttributes = interfaces.itervalues().next()
            print intfAttributes
            if isinstance(intfAttributes, list):
                # Try use the first set of attributes, but if using vlans they might not have addresses
                intfAttributes = intfAttributes[1] if not intfAttributes[0]['ipAddrs'] else intfAttributes[0]
            return intfAttributes['ipAddrs'][0].split('/')[0]

        conf.writeLine('log file %s/bgpd%s.log' % (QuaggaRouter.logDir, self.qr.name))
        conf.writeLine('hostname bgp-%s' % self.qr.name)
        conf.writeLine('password %s' % 'quagga')
        conf.writeLine('!')
        conf.writeLine('router bgp %s' % self.asNum)

        conf.indent()

        conf.writeLine('bgp router-id %s' % getRouterId(self.qr.interfaces))
        conf.writeLine('timers bgp %s' % '3 9')
        conf.writeLine('!')

        for neighbor in self.neighbors:
            conf.writeLine('neighbor %s remote-as %s' % (neighbor['address'], neighbor['as']))
            conf.writeLine('neighbor %s ebgp-multihop' % neighbor['address'])
            conf.writeLine('neighbor %s timers connect %s' % (neighbor['address'], '5'))
            conf.writeLine('neighbor %s advertisement-interval %s' % (neighbor['address'], '5'))
            if 'port' in neighbor:
                conf.writeLine('neighbor %s port %s' % (neighbor['address'], neighbor['port']))
            conf.writeLine('!')

        for route in self.routes:
            conf.writeLine('network %s' % route)

        conf.close()

class OspfProtocol(Protocol):

    """Configures and runs the OSPF protocol in Quagga."""

    def __init__(self, configFile=None, *args, **kwargs):
        self.configFile = configFile

    def config(self, **kwargs):
        if self.configFile is None:
            self.configFile = '%s/ospfd%s.conf' % (self.qr.runDir, self.qr.name)
            self.generateConfig()

        ospfPidFile = '%s/ospf%s.pid' % (self.qr.runDir, self.qr.name)

        self.qr.cmd('%s/ospfd -d -f %s -z %s -i %s'
                     % (QuaggaRouter.binDir, self.configFile, self.qr.socket, ospfPidFile))

    def generateConfig(self):
        conf = ConfigurationWriter(self.configFile)

        def getRouterId(interfaces):
            intfAttributes = interfaces.itervalues().next()
            print intfAttributes
            if isinstance(intfAttributes, list):
                # Try use the first set of attributes, but if using vlans they might not have addresses
                intfAttributes = intfAttributes[1] if not intfAttributes[0]['ipAddrs'] else intfAttributes[0]
            return intfAttributes['ipAddrs'][0].split('/')[0]

        conf.writeLine('hostname ospf-%s' % self.qr.name)
        conf.writeLine('password %s' % 'hello')
        conf.writeLine('!')
        conf.writeLine('router ospf')

        conf.indent()

        conf.writeLine('ospf router-id %s' % getRouterId(self.qr.interfaces))
        conf.writeLine('!')

        for name, intf in self.qr.interfaces.items():
            for ip in intf['ipAddrs']:
                conf.writeLine('network %s area 0' % ip)
            # if intf['ipAddrs'][0].startswith('192.168'):
            #    writeLine(1, 'passive-interface %s' % name)

        conf.close()

class PimProtocol(Protocol):

    """Configures and runs the PIM protcol in Quagga."""

    def __init__(self, configFile=None, *args, **kwargs):
        self.configFile = configFile

    def config(self, **kwargs):
        pimPidFile = '%s/pim%s.pid' % (self.qr.runDir, self.qr.name)

        self.qr.cmd('%s/pimd -Z -d -f %s -z %s -i %s'
                     % (QuaggaRouter.binDir, self.configFile, self.qr.socket, pimPidFile))

class ConfigurationWriter(object):

    """Utility class for writing a configuration file."""

    def __init__(self, filename):
        self.filename = filename
        self.indentValue = 0

        self.configFile = open(self.filename, 'w+')

    def indent(self):
        self.indentValue += 1

    def unindent(self):
        if (self.indentValue > 0):
            self.indentValue -= 1

    def write(self, string):
        self.configFile.write(string)

    def writeLine(self, string):
        intentStr = ''
        for _ in range(0, self.indentValue):
            intentStr += '  '
        self.write('%s%s\n' % (intentStr, string))

    def close(self):
        self.configFile.close()

# Backward compatibility for BGP-only use case
class BgpRouter(QuaggaRouter):

    """Quagga router running the BGP protocol."""

    def __init__(self, name, interfaces,
                 asNum=0, neighbors=[], routes=[],
                 defaultRoute=None,
                 quaggaConfFile=None,
                 zebraConfFile=None,
                 *args, **kwargs):
        bgp = BgpProtocol(configFile=quaggaConfFile, asNum=asNum, neighbors=neighbors, routes=routes)

        super(BgpRouter, self).__init__(name, interfaces,
                                        zebraConfFile=zebraConfFile,
                                        defaultRoute=defaultRoute,
                                        protocols=[bgp],
                                        *args, **kwargs)

class RouterData(object):

    """Internal data structure storing information about a router."""

    def __init__(self, index):
        self.index = index
        self.neighbors = []
        self.interfaces = {}
        self.switches = []

    def addNeighbor(self, theirAddress, theirAsNum):
        self.neighbors.append({'address': theirAddress.ip, 'as': theirAsNum})

    def addInterface(self, intf, vlan, address):
        if intf not in self.interfaces:
            self.interfaces[intf] = InterfaceData(intf)

        self.interfaces[intf].addAddress(vlan, address)

    def setSwitch(self, switch):
        self.switches.append(switch)

class InterfaceData(object):

    """Internal data structure storing information about an interface."""

    def __init__(self, number):
        self.number = number
        self.addressesByVlan = {}

    def addAddress(self, vlan, address):
        if vlan not in self.addressesByVlan:
            self.addressesByVlan[vlan] = []

        self.addressesByVlan[vlan].append(address.with_prefixlen)

class RoutedNetwork(object):

    """Creates a host behind a router. This is common boilerplate topology
    segment in routed networks."""

    @staticmethod
    def build(topology, router, hostName, networks):
        # There's a convention that the router's addresses are already set up,
        # and it has the last address in the network.

        def getFirstAddress(network):
            return '%s/%s' % (network[1], network.prefixlen)

        defaultRoute = AutonomousSystem.getLastAddress(networks[0]).ip

        host = topology.addHost(hostName, cls=RoutedHost,
                                ips=[getFirstAddress(network) for network in networks],
                                gateway=defaultRoute)

        topology.addLink(router, host)

class AutonomousSystem(object):

    """Base abstraction of an autonomous system, which implies some internal
    topology and connections to other topology elements (switches/other ASes)."""

    psIdx = 1

    def __init__(self, asNum, numRouters):
        self.asNum = asNum
        self.numRouters = numRouters
        self.routers = {}
        for i in range(1, numRouters + 1):
            self.routers[i] = RouterData(i)

        self.routerNodes = {}

        self.neighbors = []
        self.vlanAddresses = {}

    def peerWith(self, myRouter, myAddress, theirAddress, theirAsNum, intf=1, vlan=None):
        router = self.routers[myRouter]

        router.addInterface(intf, vlan, myAddress)
        router.addNeighbor(theirAddress, theirAsNum)

    def getRouter(self, i):
        return self.routerNodes[i]

    @staticmethod
    def generatePeeringAddresses():
        network = ip_network(u'10.0.%s.0/24' % AutonomousSystem.psIdx)
        AutonomousSystem.psIdx += 1

        return ip_interface('%s/%s' % (network[1], network.prefixlen)), \
            ip_interface('%s/%s' % (network[2], network.prefixlen))

    @staticmethod
    def addPeering(as1, as2, router1=1, router2=1, intf1=1, intf2=1, address1=None, address2=None, useVlans=False):
        vlan = AutonomousSystem.psIdx if useVlans else None

        if address1 is None or address2 is None:
            (address1, address2) = AutonomousSystem.generatePeeringAddresses()

        as1.peerWith(router1, address1, address2, as2.asNum, intf=intf1, vlan=vlan)
        as2.peerWith(router2, address2, address1, as1.asNum, intf=intf2, vlan=vlan)

    @staticmethod
    def getLastAddress(network):
        return ip_interface(network.network_address + network.num_addresses - 2)

    @staticmethod
    def getIthAddress(network, i):
        return ip_interface('%s/%s' % (network[i], network.prefixlen))

class BasicAutonomousSystem(AutonomousSystem):

    """Basic autonomous system containing one host and one or more routers
    which peer with other ASes."""

    def __init__(self, num, routes, numRouters=1):
        super(BasicAutonomousSystem, self).__init__(65000+num, numRouters)
        self.num = num
        self.routes = routes

    def addLink(self, switch, router=1):
        self.routers[router].setSwitch(switch)

    def build(self, topology):
        self.addRouterAndHost(topology)

    def addRouterAndHost(self, topology):

        # TODO implementation is messy and needs to be cleaned up

        intfs = {}

        router = self.routers[1]
        for i, router in self.routers.items():

            # routerName = 'r%i%i' % (self.num, i)
            routerName = 'r%i' % self.num
            if not i == 1:
                routerName += ('%i' % i)

            hostName = 'h%i' % self.num

            for j, interface in router.interfaces.items():
                nativeAddresses = interface.addressesByVlan.pop(None, [])
                peeringIntf = [{'mac' : '00:00:%02x:00:%02x:%02x' % (self.num, i, j),
                               'ipAddrs' : nativeAddresses}]

                for vlan, addresses in interface.addressesByVlan.items():
                    peeringIntf.append({'vlan': vlan,
                                        'mac': '00:00:%02x:%02x:%02x:%02x' % (self.num, vlan, i, j),
                                        'ipAddrs': addresses})

                intfs.update({'%s-eth%s' % (routerName, j-1) : peeringIntf})

            # Only add the host to the first router for now
            if i == 1:
                internalAddresses = []
                for route in self.routes:
                    internalAddresses.append('%s/%s' % (AutonomousSystem.getLastAddress(route).ip, route.prefixlen))

                internalIntf = {'ipAddrs' : internalAddresses}

                # This is the configuration of the next interface after all the peering interfaces
                intfs.update({'%s-eth%s' % (routerName, len(router.interfaces.keys())) : internalIntf})

            routerNode = topology.addHost(routerName,
                                          asNum=self.asNum, neighbors=router.neighbors,
                                          routes=self.routes,
                                          cls=BgpRouter, interfaces=intfs)

            self.routerNodes[i] = routerNode

            for switch in router.switches:
                topology.addLink(switch, routerNode)

            # Only add the host to the first router for now
            if i == 1:
                defaultRoute = internalAddresses[0].split('/')[0]

                host = topology.addHost(hostName, cls=RoutedHost,
                                        ips=[self.getFirstAddress(route) for route in self.routes],
                                        gateway=defaultRoute)

                topology.addLink(routerNode, host)

    # def getLastAddress(self, network):
    #    return ip_address(network.network_address + network.num_addresses - 2)

    def getFirstAddress(self, network):
        return '%s/%s' % (network[1], network.prefixlen)

# TODO fix this AS - doesn't currently work
class RouteServerAutonomousSystem(BasicAutonomousSystem):

    def __init__(self, routerAddress, *args, **kwargs):
        BasicAutonomousSystem.__init__(self, *args, **kwargs)

        self.routerAddress = routerAddress

    def build(self, topology, connectAtSwitch):

        switch = topology.addSwitch('as%isw' % self.num, cls=OVSBridge)

        self.addRouterAndHost(topology, self.routerAddress, switch)

        rsName = 'rs%i' % self.num
        routeServer = topology.addHost(rsName,
                                       self.asnum, self.neighbors,
                                       cls=BgpRouter,
                                       interfaces={'%s-eth0' % rsName : {'ipAddrs': [self.peeringAddress]}})

        topology.addLink(routeServer, switch)
        topology.addLink(switch, connectAtSwitch)

class SdnAutonomousSystem(AutonomousSystem):

    """Runs the internal BGP speakers needed for ONOS routing apps like
    SDN-IP."""

    routerIdx = 1

    def __init__(self, onosIps, num=1, numBgpSpeakers=1, asNum=65000, externalOnos=True,
                 peerIntfConfig=None, withFpm=False):
        super(SdnAutonomousSystem, self).__init__(asNum, numBgpSpeakers)
        self.onosIps = onosIps
        self.num = num
        self.numBgpSpeakers = numBgpSpeakers
        self.peerIntfConfig = peerIntfConfig
        self.withFpm = withFpm
        self.externalOnos = externalOnos
        self.internalPeeringSubnet = ip_network(u'1.1.1.0/24')

        for router in self.routers.values():
            # Add iBGP sessions to ONOS nodes
            for onosIp in onosIps:
                router.neighbors.append({'address': onosIp, 'as': asNum, 'port': 2000})

            # Add iBGP sessions to other BGP speakers
            for i, router2 in self.routers.items():
                if router == router2:
                    continue
                cpIpBase = self.num*10
                ip = AutonomousSystem.getIthAddress(self.internalPeeringSubnet, cpIpBase+i)
                router.neighbors.append({'address': ip.ip, 'as': asNum})

    def build(self, topology, connectAtSwitch, controlSwitch):

        natIp = AutonomousSystem.getLastAddress(self.internalPeeringSubnet)

        for i, router in self.routers.items():
            num = SdnAutonomousSystem.routerIdx
            SdnAutonomousSystem.routerIdx += 1
            name = 'bgp%s' % num

            cpIpBase = self.num*10
            ip = AutonomousSystem.getIthAddress(self.internalPeeringSubnet, cpIpBase+i)

            eth0 = { 'ipAddrs' : [ str(ip) ] }
            if self.peerIntfConfig is not None:
                eth1 = self.peerIntfConfig
            else:
                nativeAddresses = router.interfaces[1].addressesByVlan.pop(None, [])
                eth1 = [{ 'mac': '00:00:00:00:00:%02x' % num,
                          'ipAddrs' : nativeAddresses }]

                for vlan, addresses in router.interfaces[1].addressesByVlan.items():
                    eth1.append({'vlan': vlan,
                                 'mac': '00:00:00:%02x:%02x:00' % (num, vlan),
                                 'ipAddrs': addresses})

            intfs = { '%s-eth0' % name : eth0,
                      '%s-eth1' % name : eth1 }

            bgp = topology.addHost( name, cls=BgpRouter, asNum=self.asNum,
                                    neighbors=router.neighbors,
                                    interfaces=intfs,
                                    defaultRoute=str(natIp.ip),
                                    fpm=self.onosIps[0] if self.withFpm else None )

            topology.addLink( bgp, controlSwitch )
            topology.addLink( bgp, connectAtSwitch )

        if self.externalOnos:
            nat = topology.addHost('nat', cls=NAT,
                                   ip='%s/%s' % (natIp.ip, self.internalPeeringSubnet.prefixlen),
                                   subnet=str(self.internalPeeringSubnet), inNamespace=False)
            topology.addLink(controlSwitch, nat)

def generateRoutes(baseRange, numRoutes, subnetSize=None):
    baseNetwork = ip_network(baseRange)

    # We need to get at least 2 addresses out of each subnet, so the biggest
    # prefix length we can have is /30
    maxPrefixLength = baseNetwork.max_prefixlen - 2

    if subnetSize is not None:
        return list(baseNetwork.subnets(new_prefix=subnetSize))

    trySubnetSize = baseNetwork.prefixlen + 1
    while trySubnetSize <= maxPrefixLength and \
            len(list(baseNetwork.subnets(new_prefix=trySubnetSize))) < numRoutes:
        trySubnetSize += 1

    if trySubnetSize > maxPrefixLength:
        raise Exception("Can't get enough routes from input parameters")

    return list(baseNetwork.subnets(new_prefix=trySubnetSize))[:numRoutes]

class RoutingCli( CLI ):

    """CLI command that can bring a host up or down. Useful for simulating router failure."""

    def do_host( self, line ):
        args = line.split()
        if len(args) != 2:
            error( 'invalid number of args: host <host name> {up, down}\n' )
            return

        host = args[ 0 ]
        command = args[ 1 ]
        if host not in self.mn or self.mn.get( host ) not in self.mn.hosts:
            error( 'invalid host: %s\n' % args[ 1 ] )
        else:
            if command == 'up':
                op = 'up'
            elif command == 'down':
                op = 'down'
            else:
                error( 'invalid command: host <host name> {up, down}\n' )
                return

            for intf in self.mn.get( host ).intfList( ):
                intf.link.intf1.ifconfig( op )
                intf.link.intf2.ifconfig( op )
