#!/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))

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

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

    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 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 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 )
