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

try:
   import sys
   import errno
   import argparse
   import EntityManager
   import os
   from TypeFuture import TacLazyType
   from CliPlugin.MplsCli import maxIngressMplsTopLabels

   MplsOamStandard = TacLazyType( 'MplsUtils::MplsOamStandard' )

   from ClientDispatcher import(
      lspUtilHandler,
   )
   from ClientCommonLib import(
      setProductCodeGlobals,
      LspPing,
      LspPingTypes,
   )
   setProductCodeGlobals()

   p = argparse.ArgumentParser( description='LSP Ping Utility' )
   p.add_argument( 'destination', nargs='?', 
                    help='Destination to Ping, optional for RSVP' )
   p.add_argument( '--type', metavar='destination-type', choices=LspPingTypes, 
                   help='Type of the destination to Ping' )
   p.add_argument( '--vrf', metavar='VRF', 
                   help='Ping destination in VRF' )
   p.add_argument( '--src', metavar='source-address', 
                   help='Source address for Ping packet' )
   p.add_argument( '--dst', metavar='destination-address',
                   help='Destination address for Ping packet' )
   p.add_argument( '--label', metavar='label-or-label-stack',
                   help='Label or comma-separated label stack (Top of stack first)' )
   p.add_argument( '--smac', metavar='source-MAC', 
                   help='Source MAC address of Ping packet' )
   p.add_argument( '--dmac', metavar='destination-MAC', 
                   help='Destination MAC address of Ping packet' )
   p.add_argument( '--count', metavar='count', type=int, default=0,
                   help='Number of Ping packets' )
   p.add_argument( '--interval', metavar='interval', type=int, default=1,
                   help='Interval of Ping packets in seconds' )
   p.add_argument( '--interface', metavar='interface',
                   help='Egress interface of Ping packets' )
   p.add_argument( '--entry', metavar='nexthop-group-entry', type=int, default=-1,
                   help='Nexthop group entry index' )
   p.add_argument( '--verbose', metavar='verbose-output', type=bool,
                   help='Enable verbose output' )
   p.add_argument( '--nexthop', metavar='nexthop-address',
                   help='Nexthop address' )
   p.add_argument( '--tos', metavar='tos', choices=range( 0, 256 ),
                   type=int, help='Type of service' )
   p.add_argument( '--tc', metavar='traffic-class', type=int, 
                   default=0, choices=range( 0, 8 ),
                   help='MPLS traffic class field' )
   p.add_argument( '--session-id', metavar='session-id', type=int,
                   help='RSVP session ID to ping' )
   p.add_argument( '--lsp', metavar='lsp-rsvp', type=int,
                   help='RSVP LSP ID to ping' )
   p.add_argument( '--session-name', metavar='session-name', type=str,
                   help='RSVP session name to ping' )
   p.add_argument( '--color', metavar='color', type=int, help='SR-TE Policy color '
                   'value' )
   p.add_argument( '--trafficAf', metavar='trafficAf', type=str, help='The type '
                   'of traffic steered through the policy' )
   p.add_argument( '--standard', metavar='standard', type=str,
                   choices=( MplsOamStandard.arista, MplsOamStandard.ietf ),
                   help='The OAM standard to comply with for the Ping' )
   p.add_argument( '--multiLabel', metavar='multiLabel', type=int, default=1,
                   choices=[ maxIngressMplsTopLabels ],
                   help=( 'Perform validation using the specified number of '
                          'top labels during route lookups' ) )
   p.add_argument( '--size', metavar='size', type=int,
                   choices=range( 120, 10001 ),
                   help='Size of ping packet in bytes' )
   p.add_argument( '--padReply', metavar='padReply', type=bool, default=False,
                   help='Indicates that ping reply should copy the Pad TLV' )

   p.add_argument( '--genOpqVal', metavar='opaque-value', type=int,
                   help='Generic Opaque Value' )
   p.add_argument( '--sourceAddrOpqVal', metavar='source-address-opaque-value',
                   help='Source Address Opaque Value' )
   p.add_argument( '--groupAddrOpqVal', metavar='group-address-opaque-value',
                   help='Group Address Opaque Value' )
   p.add_argument( '--jitter', metavar='jitter-value', type=int,
                   help='Echo Jitter Value' )
   p.add_argument( '--responderAddr', metavar='responder-address',
                   help='Node Responder Address' )
   p.add_argument( '--egressValidateAddress', metavar='egressValidateAddress',
                   type=str, help=( 'Perform egress validation' ) )

   # arguments for testing
   p.add_argument( '--cidbase', metavar='client-id-base', type=int,
                   help='Client ID base value' )
   p.add_argument( '--sport', metavar='source-port', type=int,
                   help='UDP source port of echo request' )
   p.add_argument( '--print-args', action='store_true',
                   help='print given arguments and exit( 0 )' )

   args = vars( p.parse_args() )
   # This argument is parsed before lspUtilHandler since we do not want to create
   # an entityManager in this case.
   if args[ 'print_args' ]:
      print( args )
      sys.exit( 0 )
   # It is not needed in any case after the previous check.
   args.pop( 'print_args' )

   if args[ 'type' ] == 'rsvp':
      if ( not args[ 'session_id' ] and not args[ 'session_name' ] ) or \
         ( args[ 'session_id' ] and args[ 'session_name' ] ):
         p.error( '--type rsvp requires exclusively --session-id or --session-name' )
      elif args[ 'session_name' ] and args[ 'lsp' ]:
         p.error( '--lsp cannot be used with --session-name, use --session-id' )
   elif not args[ 'destination' ]:
      p.error( 'missing destination argument' )

   # Create entity manager here to allow easy testing of lspUtilHandler
   sysname = os.environ.get( 'SYSNAME', 'ar' )
   entityManager = EntityManager.Sysdb( sysname, agentName='LspPing' )

   sys.exit( lspUtilHandler( LspPing, entityManager, args ) )

except KeyboardInterrupt:
   sys.exit( errno.EINTR )

except SystemExit, e:
   sys.exit( e.code )

except Exception:
   raise
