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

import GenprefdlLib, GenfdlLib
from EosInit import getPrefdl

import os
import re
import rpm
import subprocess
import sys

pkgExcludeDir = '/etc/EosPkgExclude.d'

def getUnusedPackages( prefdl ):
   if not prefdl:
      return set()

   prefdlFields = GenprefdlLib.decodePrefdl( prefdl )
   registry = GenfdlLib.FdlRegistryWithKeys()
   fdls = registry.lookupFdl( sid=prefdlFields.sid,
                              baseAsy=prefdlFields.baseAsy,
                              hwApi=prefdlFields.hwApi,
                              cpuSid=prefdlFields.cpuSid,
                              cpuHwApi=prefdlFields.cpuHwApi,
                              configDict={} )

   if not fdls:
      return set()

   if isinstance( fdls, list ):
      fdls = ','.join( fdls )

   if not os.path.isfile( os.path.join( pkgExcludeDir, fdls + '.exclude' ) ):
      for k in registry.fdlKeys():
         if k.get( 'modular' ) and fdls in registry.lookupFdlWithKey( **k ):
            fdls = k[ 'group' ]
            break
      else:
         return set()

   try:
      with open( os.path.join( pkgExcludeDir, fdls + '.exclude' ) ) as f:
         return set( f.read().splitlines() )
   except IOError:
      return set()

def HardwarePkgFilename( prefdl, defaultPkgFilename ):
   pkgFilename = defaultPkgFilename
   m = re.search( r"PCA: (PCA\d{5})", prefdl )
   if not m:
      return pkgFilename

   basePca = m.groups()[ 0 ]

   if basePca == "PCA00003":
      # We're running against a StHelena
      pkgFilename = "vintageNapa"
   elif basePca == "PCA00040":
      # We're running against a GlenEllen
      pkgFilename = "vintageNapa"
   elif basePca == "PCA00011":
      # We're running against a Sonoma
      pkgFilename = "vintageNapa"

   return pkgFilename

def getExcludedPackages( prefdl ):
   # Inspects the EosPkgExclude.d directory for packages
   # that different platforms want to exclude at runtime
   # from the running EOS image and removes the rpms

   sid = ""
   cmdlineFilename = '/proc/cmdline'
   if prefdl:
      try:
         sid = GenprefdlLib.decodePrefdl( prefdl ).sid
      except TypeError:
         # vEOS has an incomplete prefdl, which is okay
         pass
   pkgFilename = 'default'

   with open( cmdlineFilename ) as cmdLineFile:
      m = re.search( r"platform=(\w+)", cmdLineFile.read() )
   if m:
      pkgFilename = m.group( 1 )
   else:
      # Some products don't set platform string, check PCA
      pkgFilename = HardwarePkgFilename( prefdl, pkgFilename )

   pkgFilePath = os.path.join( pkgExcludeDir, pkgFilename )
   try:
      with open( pkgFilePath ) as pkgFile:
         return pkgFile.read().splitlines()
   except IOError:
      defaultFilePath = os.path.join( pkgExcludeDir, 'default' )
      with open( defaultFilePath ) as pkgFile:
         return pkgFile.read().splitlines()

def main():
   prefdl = getPrefdl()
   pkgsToRemove = getUnusedPackages( prefdl )
   pkgsToRemove.update( getExcludedPackages( prefdl ) )

   ts = rpm.ts()
   mi = ts.dbMatch()
   pkgsInstalled = [ h[ 'name' ] for h in mi ]

   pkgsToRemove.intersection_update( pkgsInstalled )

   if not pkgsToRemove:
      sys.exit( 0 )

   try:
      import sysconfig
      subprocess.check_call( "LD_PRELOAD=" + sysconfig.get_config_var( 'LIBDIR' ) +
                             "/libremovexattr_stub.so rpm -e --nodeps " +
                             ' '.join( pkgsToRemove ), shell=True )
   except subprocess.CalledProcessError, e:
      print "Removal of excluded packages failed", e

if __name__ == "__main__":
   main()
