#!/usr/bin/python

'''
Notes:

This file contains classes and methods useful for integrating LincOE with Mininet, 
such as startOE, stopOE, OpticalLink, and OpticalSwitch

- $ONOS_ROOT ust be set
- Need to run with sudo -E to preserve ONOS_ROOT env var
- We assume LINC-Config-Generator is named LINC-Config-Generator
- We also assume linc-oe is named linc-oe
- LINC-config-generator and linc-oe must be subdirectories of the user's
  home directory

            TODO
        -----------
    - clean up files after runtime
        - maybe save the old files in a separate directory?
    - modify script to allow startOE to run before net.start()
    - add ONOS as a controller in script

            Usage:
        ------------
    - import OpticalLink and OpticalSwitch from this module
    - import startOE and stopOE from this module
    - create topology as you would a normal topology. when 
      to an optical switch with topo.addLink, always specify cls=OpticalLink
    - when creating an optical switch, use cls=OpticalSwitch in topo.addSwitch
    - for annotations on links and switches, a dictionary must be passed in as
      the annotations argument
    - startOE must be run AFTER net.start() with net as an argument.
    - stopOE can be run at any time

I created a separate function to start lincOE to avoid subclassing Mininet.
In case anyone wants to write something that DOES subclass Mininet, I
thought I would outline how:

If we want an object that starts lincOE within the mininet class itself,
we need to add another object to Mininet that contains all of the json object
information for each switch. We would still subclass switch and link, but these
classes would basically be dummy classes that store their own json information
in the Mininet class object. We may also change the default switch class to add
it's tap interfaces from lincOE during startup. The start() method for mininet would 
grab all of the information from these switches and links, write configuration files
for lincOE using the json module, start lincOE, then run the start methodfor each
switch. The new start() method for each switch would parse through the sys.config
file that was created and find the tap interface it needs to connect to, similar 
to the findTap function that I currently use. After all of the controllers and 
switches have been started, the new Mininet start() method should also push the 
Topology configuration file to ONOS.

'''

import re
import json
import os
from time import sleep

from mininet.node import Switch, RemoteController
from mininet.topo import Topo
from mininet.util import quietRun
from mininet.net import Mininet
from mininet.log import  setLogLevel, info, error, warn
from mininet.link import Link, Intf
from mininet.cli import CLI

class OpticalSwitch( Switch ):

    def __init__( self, name, dpid=None, allowed=True,
                  switchType='ROADM', annotations={}, **params ):
        params[ 'inNamespace' ] = False
        Switch.__init__( self, name, dpid=dpid, **params )
        self.name = name
        self.annotations = annotations
        self.allowed = allowed
        self.switchType = switchType
        self.configDict = {} # dictionary that holds all of the JSON configuration data

    def start( self, *opts, **params ):
        '''Instead of starting a virtual switch, we build the JSON
           dictionary for the emulated optical switch'''
        self.configDict[ 'uri' ] = 'of:' + self.dpid
        self.configDict[ 'annotations' ] = self.annotations
        self.configDict[ 'annotations' ].setdefault( 'name', self.name )
        self.configDict[ 'hw' ] = 'OE'
        self.configDict[ 'mfr' ] = 'Linc'
        self.configDict[ 'mac' ] = 'ffffffffffff' + self.dpid[-2] + self.dpid[-1]
        self.configDict[ 'type' ] = self.switchType
        self.configDict[ 'ports' ] = []
        for port, intf in self.intfs.items():
            if intf.name == 'lo':
                continue
            else:
                self.configDict[ 'ports' ].append( intf.json() )


    def json( self ):
        "return json configuration dictionary for switch"
        return self.configDict
    
    def terminate( self ):
        pass

class OpticalLink( Link ):

    def __init__( self, node1, node2, port1=None, port2=None, allowed=True,
                  intfName1=None, intfName2=None, linkType='OPTICAL',
                  annotations={}, speed1=0, speed2=0, **params ):
        "Creates a dummy link without a virtual ethernet pair."
        self.allowed = allowed
        self.annotations = annotations
        self.linkType = linkType
        params1 = { 'speed': speed1 }
        params2 = { 'speed': speed2 }
        
        if isinstance( node1, OpticalSwitch ):
            cls1 = OpticalIntf
        else:
            cls1 = Intf
            # bad hack to stop error message from appearing when we try to set up intf in a packet switch, 
            # and there is no interface there( because we do not run makeIntfPair ). This way, we just set lo up
            intfName1 = 'lo'
        if isinstance( node2, OpticalSwitch ):
            cls2 = OpticalIntf
        else:
            cls2 = Intf
            intfName2 = 'lo'
        Link.__init__( self, node1, node2, port1=port1, port2=port2,
                       intfName1=intfName1, intfName2=intfName2, cls1=cls1,
                       cls2=cls2, params1=params1, params2=params2 )
        

    @classmethod
    def makeIntfPair( _cls, intfName1, intfName2, *args, **kwargs ):
        pass

    def json( self ):
        "build and return the json configuration dictionary for this link"
        configData = {}
        configData[ 'src' ] = ( 'of:' +  self.intf1.node.dpid + 
                                '/%s' % self.intf1.node.ports[ self.intf1 ] )
        configData[ 'dst' ] = ( 'of:' +  self.intf2.node.dpid +
                                '/%s' % self.intf2.node.ports[ self.intf2 ] )
        configData[ 'type' ] = self.linkType
        configData[ 'annotations' ] = self.annotations
        return configData

class OpticalIntf( Intf ):

    def __init__( self, name=None, node=None, speed=0, 
                  port=None, link=None, **params ):
        self.node = node
        self.speed = speed
        self.port = port
        self.link = link
        self.name = name
        node.addIntf( self, port=port )
        self.params = params
        self.ip = None

    def json( self ):
        "build and return the JSON information for this interface( not used right now )"
        configDict = {}
        configDict[ 'port' ] = self.port
        configDict[ 'speed' ] = self.speed
        configDict[ 'type' ] = 'FIBER'
        return configDict

    def config( self, *args, **kwargs ):
        "dont configure a dummy interface"
        pass

def switchJSON( switch ):
    "Returns the json configuration for a packet switch"
    configDict = {}
    configDict[ 'uri' ] = 'of:' + switch.dpid
    configDict[ 'mac' ] = quietRun( 'cat /sys/class/net/%s/address' % switch.name ).strip( '\n' ).translate( None, ':' )
    configDict[ 'hw' ] = 'PK' # FIXME what about OVS?
    configDict[ 'mfr' ] = 'Linc' # FIXME what about OVS?
    configDict[ 'type' ] = 'SWITCH' # FIXME what about OVS?
    annotations = switch.params.get( 'annotations', {} )
    annotations.setdefault( 'name', switch.name )
    configDict[ 'annotations' ] = annotations
    ports = []
    for port, intf in switch.intfs.items():
        if intf.name == 'lo':
            continue
        portDict = {}
        portDict[ 'port' ] = port
        portDict[ 'type' ] = 'FIBER' if isinstance( intf.link, OpticalLink ) else 'COPPER'
        intfList = [ intf.link.intf1, intf.link.intf2 ]
        intfList.remove( intf )
        portDict[ 'speed' ] = intfList[ 0 ].speed if isinstance( intf.link, OpticalLink ) else 0
        ports.append( portDict )
    configDict[ 'ports' ] = ports
    return configDict


def startOE( net, controllerIP=None, controllerPort=None ):
    "Start the LINC optical emulator within a mininet instance"
    opticalJSON = {}
    linkConfig = []
    devices = []
    
    # if we are not given a controller IP or Port, we use the first found in Mininet
    if controllerIP is None:
        controllerIP = net.controllers[ 0 ].ip
    if controllerPort is None:
        controllerPort = net.controllers[ 0 ].port

    for switch in net.switches:
        if isinstance( switch, OpticalSwitch ):
            devices.append( switch.json() )
        else:
            devices.append( switchJSON( switch ) )
    opticalJSON[ 'devices' ] = devices

    for link in net.links:
        if isinstance( link, OpticalLink ) :
            linkConfig.append( link.json() )

    opticalJSON[ 'links' ] = linkConfig

    try:
        onosDir = os.environ[ 'ONOS_ROOT' ]
    except:
        onosDir = findDir( 'onos' )
        os.environ[ 'ONOS_ROOT' ] = onosDir
        if not onosDir:
            error( 'Please set ONOS_ROOT environment variable!\n' )
            return False

    info( '*** Writing Topology.json file\n' )
    with open( 'Topology.json', 'w' ) as outfile:
        json.dump( opticalJSON, outfile, indent=4, separators=(',', ': ') )

    info( '*** Converting Topology.json to linc-oe format (TopoConfig.json) file\n' )
    output = quietRun( '%s/tools/test/bin/onos-oecfg ./Topology.json > TopoConfig.json' % onosDir, shell=True )
    if output:
        error( '***ERROR: Error creating topology file: %s ' % output + '\n' )
        return False

    info( '*** Creating sys.config...\n' )
    configGen = findDir( 'LINC-config-generator' )
    if not configGen:
        error( "***ERROR: Could not find LINC-config-generator in user's home directory\n" )
        return False
    output = quietRun( '%s/config_generator TopoConfig.json %s/sys.config.template %s %s'
                    % ( configGen, configGen, controllerIP, controllerPort ), shell=True )
    if output:
        error( '***ERROR: Error creating sys.config file: %s\n' % output )
        return False

    info( '*** Copying sys.config to linc-oe directory: ', output + '\n' )
    lincDir = findDir( 'linc-oe' )
    if not lincDir:
        error( "***ERROR: Could not find linc-oe in user's home directory\n" )
        return False
    output = quietRun( 'cp -v sys.config %s/rel/linc/releases/1.0/' % lincDir, shell=True ).strip( '\n' )
    info( output + '\n' )

    info( '*** Starting linc OE...\n' )
    output = quietRun( '%s/rel/linc/bin/linc start' % lincDir, shell=True )
    if output:
        error( '***ERROR: LINC-OE: %s' % output + '\n' )
        quietRun( '%s/rel/linc/bin/linc stop' % lincDir, shell=True )
        return False
    
    info( '*** Waiting for linc-oe to start...\n' )
    waitStarted( net )
    
    info( '*** Adding cross-connect (tap) interfaces to packet switches...\n' )
    for link in net.links:
        if isinstance( link, OpticalLink ):
            if link.annotations[ 'optical.type' ] == 'cross-connect':
                for intf in [ link.intf1, link.intf2 ]:
                    if not isinstance( intf, OpticalIntf ):
                        intfList = [ intf.link.intf1, intf.link.intf2 ]
                        intfList.remove( intf )
                        intf2 = intfList[ 0 ]
                        intf.node.attach( findTap( intf2.node, intf2.node.ports[ intf2 ] ) )

    info( '*** Press any key to push Topology.json to onos...\n' )
    raw_input() # FIXME... we should eventually remove this
    info( '*** Pushing Topology.json to ONOS\n' )
    output = quietRun( '%s/tools/test/bin/onos-topo-cfg %s Topology.json' % ( onosDir, controllerIP ), shell=True )
    # successful output contains the two characters '{}'
    # if there is more output than this, there is an issue
    if output.strip( '{}' ):
        warn( '***WARNING: Could not push topology file to ONOS: %s' % output )
                        
def waitStarted( net, timeout=None ):
    "wait until all tap interfaces are available"
    tapCount = 0
    time = 0
    for link in net.links:
        if isinstance( link, OpticalLink ):
            if link.annotations[ 'optical.type' ] == 'cross-connect':
                tapCount += 1
    
    while True:
        if str( tapCount ) == quietRun( 'ip addr | grep tap | wc -l', shell=True ).strip( '\n' ):
            return True
        if timeout:
            if time >= timeout:
                error( '***ERROR: Linc OE did not start within %s seconds' % timeout )
                return False
            time += .5
        sleep( .5 )

def stopOE():
    "stop the optical emulator"
    info( '*** Stopping linc OE...\n' )
    lincDir = findDir( 'linc-oe' )
    quietRun( '%s/rel/linc/bin/linc stop' % lincDir, shell=True )

def findDir( directory ):
    "finds and returns the path of any directory in the user's home directory"
    user = findUser()
    homeDir = '/home/' + user
    Dir = quietRun( 'find %s -maxdepth 1 -name %s -type d' % ( homeDir, directory ) ).strip( '\n' )
    DirList = Dir.split( '\n' )
    if not Dir:
        return None
    elif len( DirList ) > 1 :
        warn( '***WARNING: Found multiple instances of %s; using %s\n'
                 % ( directory, DirList[ 0 ] ) )
        return DirList[ 0 ]
    else:
        return Dir

def findUser():
    "Try to return logged-in (usually non-root) user"
    try:
        # If we're running sudo
        return os.environ[ 'SUDO_USER' ]
    except:
        try:
            # Logged-in user (if we have a tty)
            return quietRun( 'who am i' ).split()[ 0 ]
        except:
            # Give up and return effective user
            return quietRun( 'whoami' )


def findTap( node, port, path=None ):
    '''utility function to parse through a sys.config
       file to find tap interfaces for a switch'''
    switch=False
    portLine = ''
    intfLines = []

    if path is None:
        lincDir = findDir( 'linc-oe' )
        if not lincDir:
            error( '***ERROR: Could not find linc-oe in users home directory\n' )
            return None
        path = '%s/rel/linc/releases/1.0/sys.config' % lincDir

    with open( path ) as f:
        for line in f:
            if 'tap' in line:
                intfLines.append( line )
            if node.dpid in line.translate( None, ':' ):
                switch=True
                continue
            if switch:
                if 'switch' in line:
                    switch = False
                if 'port_no,%s}' % port in line:
                    portLine = line
                    break 

    if portLine:
        m = re.search( 'port,\d+', portLine )
        port = m.group( 0 ).split( ',' )[ 1 ]
    else:
        error( '***ERROR: Could not find any ports in sys.config\n' )
        return

    for intfLine in intfLines:
        if 'port,%s' % port in intfLine:
            return re.findall( 'tap\d+', intfLine )[ 0 ]


class MininetOE( Mininet ):
    "Mininet with Linc-OE support (starts and stops linc-oe)"

    def start( self ):
        Mininet.start( self )
        startOE( self )

    def stop( self ):
        Mininet.stop( self )
        stopOE()

    def addControllers( self, controllers ):
        i = 0
        for ctrl in controllers:
            self.addController( RemoteController( 'c%d' % i, ip=ctrl ) )


class OpticalTestTopo( Topo ):

    def build( self ):
        opticalAnn = { 'optical.waves': 80, 'optical.type': "WDM", 'durable': True }
        switchAnn = { 'bandwidth': 100000, 'optical.type': 'cross-connect', 'durable': True }
        h1 = self.addHost( 'h1' )
        h2 = self.addHost( 'h2' )
        s1 = self.addSwitch( 's1' )
        s2 = self.addSwitch( 's2' )
        O4 = self.addSwitch( 'O4', cls=OpticalSwitch )
        O5 = self.addSwitch( 'O5', cls=OpticalSwitch )
        O6 = self.addSwitch( 'O6', cls=OpticalSwitch )
        self.addLink( O4, O5, cls=OpticalLink, annotations=opticalAnn )
        self.addLink( O5, O6, cls=OpticalLink, annotations=opticalAnn )
        self.addLink( s1, O4, cls=OpticalLink, annotations=switchAnn )
        self.addLink( s2, O6, cls=OpticalLink, annotations=switchAnn )
        self.addLink( h1, s1 )
        self.addLink( h2, s2 )

if __name__ == '__main__':
    import sys
    if len( sys.argv ) >= 2:
        controllers = sys.argv[1:]
    else:
        print 'Usage: ./opticalUtils.py (<Controller IP>)+'
        print 'Using localhost...\n'
        controllers = [ '127.0.0.1' ]

    setLogLevel( 'info' )
    net = MininetOE( topo=OpticalTestTopo(), controller=None, autoSetMacs=True )
    net.addControllers( controllers )
    net.start()
    CLI( net )
    net.stop()
