#!/usr/bin/env python
# Copyright (c) 2007 Arastra, Inc.  All rights reserved.
# Arastra, Inc. Confidential and Proprietary.


import sys, optparse, os, Tac

usageStr = ("usage: PhyEthtoolConfig add interface [interface...]\n"
            "       PhyEthtoolConfig remove interface [interface...]\n"
            "       PhyEthtoolConfig list\n\n"
            "This script configures PhyEthtool to manage interfaces.\n"
            "It is an alternative to having Fru/fdl configure PhyEthtool.\n"
            "It is useful in your workspace, so you can run:\n\n"
            "   % Sysdb &\n"
            "   % PhyEthtoolConfig add eth0\n"
            "   % PhyEthtool &\n" )
def usage():
   sys.stderr.write( usageStr )
   sys.exit( 1 )

phyConfig_ = None
ethIntfStatus_ = None

def mountStuff():
   global phyConfig_
   global ethIntfStatus_
   import EntityManager
   em = EntityManager.Sysdb( sysname=opts.sysname )
   root = em.root()
   import Cell
   cellId = Cell.cellId()
   mg = em.mountGroup()
   hwCell = mg.mount( 'hardware/cell', 'Tac::Dir', 'r' )
   mg.close( blocking=True )
   mg = em.mountGroup()
   hwCellDir = mg.mount( 'hardware/cell/%d' % cellId, 'Tac::Dir', 'w' )
   ethIntfStatus_ = mg.mount( 'interface/status/eth/phy',
          'Interface::EthPhyIntfStatusDir', 'w' )

   mg.close( blocking=True )

   try:
      hwCellDir['phy']['ethtool']['config']
   except KeyError:
      peDir = hwCellDir.mkdir( "phy/ethtool" )
      peDir.newEntity( 'Hardware::Phy::EthtoolConfig', 'config', mountPoint=True )
      
   mg = em.mountGroup()
   phyConfig_ = mg.mount( 'hardware/cell/%s/phy/ethtool/config' % cellId,
                          'Hardware::Phy::EthtoolConfig', 'w' )
   mg.close( blocking=True )


def phyConfig():
   if not phyConfig_: mountStuff()
   return phyConfig_

def ethIntfStatus():
   if not ethIntfStatus_: mountStuff()
   return ethIntfStatus_


def findEthIntfStatus( deviceName ):
   eis = ethIntfStatus()
   for intf in eis:
      if eis[intf].deviceName == deviceName:
         return intf
   return None


def addCmd( args ):
   pc = phyConfig()
   eis = ethIntfStatus()
   for deviceName in args:
      addrName = '/sys/class/net/%s/address' % deviceName
      if not os.path.exists( addrName ):
         sys.stderr.write( "%s: no such interface\n" % deviceName )
         continue
      addr = file( addrName ).read().strip()
      eintf = findEthIntfStatus( deviceName )
      if not eintf:
         for i in xrange(1, 255):
            intfName = 'Management%d' % i
            if not eis.has_key( intfName ): break
         eintf = eis.newIntfStatus( intfName, None, eis.genIdMarker, addr )
         eintf.deviceName = deviceName
      else:
         assert eintf.burnedInAddr == addr
      pc.newPhy( eintf.name, eintf )
   Tac.flushEntityLog()
   
def listCmd():
   pc = phyConfig()
   for m in pc.phy.members():
      print pc.phy[m].ethIntfStatus.deviceName, "(interface name: %s)" % m
   
def removeCmd( args ):
   pc = phyConfig()
   for deviceName in args:
      eintf = findEthIntfStatus( deviceName )
      if not eintf:
         sys.stderr.write( "%s: EthIntfStatus not found\n" % deviceName )
         continue
      if not pc.phy.has_key( intf.name ):
         sys.stderr.write( "%s (interface %s): not being managed by PhyEthtool\n" %(
            deviceName, intf.name ))
         continue
      del pc.phy[intf.name]
   Tac.flushEntityLog()
   
op = optparse.OptionParser( usage=usageStr )
op.add_option( '--sysname', action='store', default='ar',
               help='Set system name (default: %default)' )
opts, args = op.parse_args()

args = sys.argv[1:]
if not args: usage()


cmd = args.pop( 0 )
if cmd == 'add':
   addCmd( args )
elif cmd == 'remove':
   removeCmd( args )
elif cmd == 'list':
   if args: usage()
   listCmd()
else:
   usage()
   
