This discussion has been locked. The information referenced herein may be inaccurate due to age, software updates, or external references.
You can no longer post new replies to this discussion. If you have a similar question you can start a new discussion in this forum.

Avaya G250/G350 Media Gateways...

Has anyone created a custom script for Kiwi Cat Tools that works with the Avaya G250/G350 Media Gateways?

I am currently working to create one. It seems to run fine, but the config file stored is blank. I was hoping someone out there already found a solution for this. I will keep working on it and post the config if I am able to get it working correctly.

 

Thanks.

  • Hi toosober,

    Respect to you for using the custom scripting. In CatTools you can create a device capture file when you run your script which will help you see what's happenning.

    A device capture file records the communication between CatTools and the device you are having trouble with. You can create a device capture file as follows :

    # Use the CatTools File menu to select the "Enable capture mode" option.
    # Run the activity you are having trouble with. This should create a debug file in the \Debug folder.

    Reading the debug files is a bit of a black art but it should show you whether the config is being generated or whether your script is 'falling down' before this point.

    Kind regards,

    Wardini

  • Thanks Wardini for the tip on debugging. It turns out my script is failing as you thought. I will have to keep working on it.

     

    Thanks!

  • No worries. Post back here if you need further assistance.

    Kind regards,

    Wardini

  • I'm new toCatTools, and we have some Avaya G250/G350 Gateways.  I'd be very interested in getting a copy of your script if you get it working so we could include them with our backups of our network switches.

  • I worked with Paul O'Rourke at Solar Winds and he was able to get it working. The only problem is the Avaya config has a timestamp so everytime it runs the G250/350's show up as "changed". Also, occasionally they fail, but I am fine with that. I don't see a way to upload, so I will copy and paste the 2 files. The bold heading is the actual filename. Hope they work for you.

    Custom Avaya MediaGateway.ini

    [info]
    cookie=Kiwi CatTools
    version=3
    author=Kiwi Enterprises

    [device]
    name=Custom.Avaya.MediaGateway
    id=4000

    # Device info

    [item_Group]
    name=Group
    default=Default
    required=1
    info="The logical group that this device belongs to."

    [item_Name]
    name=Name
    default=Custom Device Template
    required=1
    info="A unique name for this device. e.g. sales-router or head-office-3500."

    [item_HostAddress]
    name=Host Address
    default=127.0.0.1
    required=1
    info="IP address or host name of the device."

    [item_Filename]
    name=File Name
    default=
    required=1
    info="The base file name to use for this device (unique)."

    [item_Model]
    name=Model
    default=G250/G350
    required=0
    info="The device model number."
    list=Custom

    [item_ConnectVia]
    name=Connect via
    default=Direct connect
    required=1
    info="The name of another device to connect to first."

    [item_Telnet]
    name=Method
    default=Telnet
    required=1
    list=Telnet,Cisco SSH,SSH1,SSH2,SSH2-nopty,SSH1-DES,SSH1-3DES,SSH1-Blowfish
    info="Connection method to use."

    [item_TelnetPort]
    name=Port
    default=23
    required=1
    list=23,22
    info="Port number to use."

    # Passwords

    [item_VTYPass]
    name=VTY Password
    default=
    required=0
    info="VTY password."

    [item_EnablePass]
    name=Enable Password
    default=
    required=0
    info="Enable or privilege password."

    [item_PrivilegeLevel]
    name=Privilege Level
    default=
    required=0
    info="Sets the enable mode privilege level. (Not required in most cases)"

    [item_ConsolePass]
    name=Console Password
    default=
    required=0
    info="The console (com port connection) password."

    [item_AAAUsername]
    name=Username
    default=
    required=0
    info="AAA/TACACS/RADIUS/Local username."

    [item_AAAPassword]
    name=Password
    default=
    required=0
    info="AAA/TACACS/RADIUS/Local password."

    [item_SNMPRead]
    name=SNMP Read
    default=
    required=0
    info="SNMP Read community name."

    [item_SNMPWrite]
    name=SNMP Write
    default=
    required=0
    info="SNMP Write community name."

    [item_RequireVTYLogin]
    name=Initial login requires password
    default=1
    required=0
    info="This device requires an initial password for access"

    [item_LoginUsesAAA]
    name=Initial login requires username/password
    default=0
    required=0
    info="The initial access requires a username and password"

    [item_EnableUsesAAA]
    name=Enable mode requires username/password
    default=0
    required=0
    info="Enable mode access requires a username and password"

    # Prompts

    [item_VTYPrompt]
    name=VTY Prompt
    info="Expected VTY prompt from the device. (Only required if non standard prompt is used)"

    [item_EnablePrompt]
    name=Enable Prompt
    info="Expected enable mode prompt from the device. (Only required if non standard prompt is used)"

    [item_ConsolePrompt]
    name=Console Prompt
    info="Expected console prompt from the device. (Only required if non standard prompt is used)"

    [item_AAAUserPrompt]
    name=Username prompt
    info="Expected Username prompt from the device or AAA server. (Only required if non standard prompt is used)"

    [item_AAAPassPrompt]
    name=Password prompt
    info="Expected AAA Password prompt from the device or AAA server. (Only required if non standard prompt is used)"

    # Contact info

    [item_Address1]
    name=Address1
    default=
    required=0
    info="Location of the device"

    [item_Address2]
    name=Address2
    default=
    required=0
    info="Location of the device"

    [item_Address3]
    name=Address3
    default=
    required=0
    info="Location of the device"

    [item_ContactName]
    name=Contact Name
    default=
    required=0
    info="The name of the person responsible for this device."

    [item_ContactPhone]
    name=Contact Phone
    default=
    required=0
    info="How to contact the person responsible for this device"

    [item_ContactEmail]
    name=Contact E-mail
    default=
    required=0
    info="How to contact the person responsible for this device"

    [item_ContactOther]
    name=Contact Other
    default=
    required=0
    info="Any additional contact info"

    [item_AlertEmail]
    name=Alert e-mail
    default=
    required=0
    info="Who to notify by e-mail of any alarms or alerts for this device"

    [item_SerialNumber]
    name=Serial number
    default=
    required=0
    info="The serial number of this device"

    [item_AssetTag]
    name=Asset Tag
    default=
    required=0
    info="Asset tag information"

    [item_Identification]
    name=Identification
    default=
    required=0
    info="Identification info for this device"

    [item_SerialOther]
    name=Other info
    default=
    required=0
    info="Any other serial number information"

    [item_ActivitySpecific1]
    name=Activity Specific1
    default=
    required=0
    info="Information specific to a particular activity"

    [item_ActivitySpecific2]
    name=Activity Specific2
    default=
    required=0
    info="Information specific to a particular activity"

    Custom Avaya MediaGateway.txt

    Attribute VB_Name = "Dev_CustomDeviceTemplate"
    Option Explicit

    Private Const SCRIPT_NAME = "Device Template"
    Private Const DEVICE_USERNAMEPROMPT ="Login:"
    Private Const DEVICE_PASSWORDPROMPT = "Password:"
    Private Const DEVICE_STANDARDPROMPT = "#"
    Private Const DEVICE_PRIVILEGEDPROMPT = ""
    Private Const DEVICE_CONFIGPROMPT = ""
    Private Const DEVICE_MORETEXT = "--type q to quit or space key to continue--"
     
    Private Const DEVICE_INVALIDCOMMAND = "Command not found, try: help"    ' Get this by typing BlahBlahBlah<cr>
    Private Const DEVICE_INCOMPLETECOMMAND = "Incomplete command , try help"        ' Get this by typing Copy<cr>
    Private Const DEVICE_YESNOTEXT = "(Y/N)?"
    Private Const DEVICE_CONFIGHEADERTEXT = "Generating configuration:"    ' Text to trim off the top of a config output before saving it.  Set to "" if no header to remove.

    ' If device does not have a command then set to ""
    Private Const COMMAND_ENTERENABLEMODE = ""
    Private Const COMMAND_EXITENABLEMODE = ""
    Private Const COMMAND_ENTERCONFIG = ""
    Private Const COMMAND_EXITCONFIG = ""
    Private Const COMMAND_DISABLEPAGING = "terminal length 200"
    Private Const COMMAND_ENABLEPAGING = "terminal length 24" ' Set back to the device default of 24 lines per page
    Private Const COMMAND_RUNNINGCONFIG = "show run"
    Private Const COMMAND_STARTUPCONFIG = "show start"
    Private Const COMMAND_SAVENVRAM = "copy running-config startup-config"
    Private Const COMMAND_DISCONNECT = "exit"  ' * The command used to end the session on the device (logout/logoff/exit, etc.)
    Private Const COMMAND_TIMEOUT = 30  ' in seconds.  It is not recommended you alter this default value.
     
    ' ------------------------------------------------- SCRIPT NOTES -------------------------------------------------
    '
    ' CONSTANTS: (user to review and amend accordingly for the custom device).
    '   The above declared Constants are based on commands supported by a Cisco router.
    '   When setting up your custom device, modify these Constants to suit your device.
    '   If the command is not valid for your device, set the Constant value to be an empty string.
    '   Do NOT delete the Constant, it may be referenced in the script, even if no value is set.
    '   If not declared errors could occur at run-time.
    '   * NOTE: ensure the COMMAND_DISCONNECT is correct for your device otherwise the device may respond with an
    '   invalid command message and therefore fail your activity.
    '
    ' TASKS TO COMPLETE DURING INITIAL SCRIPT SETUP: (user to complete).
    '   Function: SendPassword
    '      rgMult(2) is set to the initial value of "Incorrect Password!", valid for a Cisco Router.
    '      Please change rgMult(2) accordingly for your device.
    '
    ' ADDITIONAL TASKS POST INITIAL SCRIPT SETUP: (user to update as and when encountered).
    '   Function: SendPassword
    '      Add any additional rgMult() items you encounter when sending the password or logging on to the device.
    '   Function: SendUsername
    '      Add any additional rgMult() items you encounter when sending the username or logging on to the device.
    '
    ' FUNCTIONS:
    '   Each function header contains a list of functions/procedures called from within the function.
    '   This list excludes calls to any of the internal CatTools functions which are prefixed with "cl."
    '   A full list of cl. functions exposed to the template including a brief description and example how to
    '   use them can be found in our one line help file at http://www.kiwisyslog.com/help/cattools/index.html
    '
    ' ------------------------------------------------- DEVICE NOTES -------------------------------------------------
    '
    ' CUSTOM SCRIPT: Cisco Router (overwrite with your device name)
    '   This is a custom device script for a Cisco Router...[add your device information here]
    '
    '
    ' Custom activity added
    '
    ' ------------------------------------------------- END OF NOTES -------------------------------------------------


    Function login()
    ' The Function Login() is the initial entry point for a login to a device.
    ' It queries the connection method specified in the device setup, and redirects to the relevant login function.
    ' If login successful it calls on a function to determine the device hostname.
    '
    ' Calls On:         LoginTelnet, LoginSSH, DetermineHostname
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)

       
        ' Declare variables
        Dim bLoginOK
       
        ' Initialise client variables
        cl.Initialise

        ' Default function return value
        login = False
       
        ' Send level 4 (debug) message to infolog
        cl.Log 4, "Login " & SCRIPT_NAME & ": " & cl.CurDevName
       
        ' Query device connection method and redirect to relevant login function
        Select Case LCase(Left(cl.CurDevTelnet, 3))
        Case "tel"
            bLoginOK = LoginTelnet
        Case "ssh"
            bLoginOK = LoginSSH
        Case Else
            ' Unknown
        End Select
       
        If bLoginOK = True Then
            ' Successful login
            cl.Log 4, "Login to " & cl.CurDevName & " was successful"
           
            ' Call function to determine the device hostname
            If DetermineHostname = True Then
                cl.Log 4, "DeviceHostnameID: " & cl.DeviceHostnameID
                login = True
            End If
       
        Else ' Failed login
            cl.Log 4, "Login to " & cl.CurDevName & " failed"
        End If
       
    End Function


    Function LoginTelnet()
    ' The Function LoginTelnet() is called if connecting to the device using Telnet.
    ' It reads the response buffer from the device and redirects to the relevant login authentication function.
    '
    ' Calls On:         LoginAAA, SendPassword
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
       
        ' Declare variables
        Dim rgMult     ' array of multiple items
        Dim iRetVal
        Dim bSentCR
        Dim bContinue

        ' Default function return value
        LoginTelnet = False
       
        ' Redimension rgMult to number of response items we are testing for (increment accordingly when adding new values)
        ' *Note: rgMult is really a 0 (zero) based array.  Element rgMult(0) is not specified as this is returned by the
        ' function if none of the others elements are found
        ReDim rgMult(5)
       
        ' Expected possible default return values in order we want to test for them
        rgMult(1) = DEVICE_USERNAMEPROMPT
        rgMult(2) = DEVICE_PASSWORDPROMPT
        'rgMult(3) = ... add additional rgMults if required
       
        ' Override defaults if required (i.e. custom prompts set in device setup - Prompts tab)
        If Len(cl.CurDevAAAUserPrompt) > 0 Then rgMult(1) = cl.CurDevAAAUserPrompt
        If Len(cl.CurDevVTYPrompt) > 0 Then rgMult(2) = cl.CurDevVTYPrompt
       
        ' If the device has no user security then check for just the device prompts (i.e. getting straight in after connection)
        ' *NOTE: This is not a recommended configuration for your device.  The script may have undesirable results if these
        ' chars exist in your device banner
        If cl.CurDevRequireVTYLogin = "0" And cl.CurDevLoginUsesAAA = "0" Then
            ' *NOTE: Always set device prompts as last items to check for
            rgMult(4) = DEVICE_STANDARDPROMPT
            rgMult(5) = DEVICE_PRIVILEGEDPROMPT
        End If
       
        ' Default the variables and start the login process
        bSentCR = False
        bContinue = True
       
        Do While bContinue = True
            ' Only loop back if instructed to do so
            bContinue = False
           
            ' Compare device response buffer to our response array (rgMult). Each Case below refers to the rgMults above.
            iRetVal = cl.WaitForMultData(rgMult, , COMMAND_TIMEOUT)
           
            Select Case iRetVal
            Case 0 ' Device response not one we are expecting
                ' Check if response buffer is empty or not
                If Len(cl.RxBuffer) = 0 Then
                    ' Send a <CR> to try 'wake the device up'. *NOTE: do only the once
                    If Not bSentCR Then
                        cl.SendData vbCr
                        bSentCR = True
                        bContinue = True
                    Else ' Still no device response
                        cl.Log 1, "Did not receive VTY entry prompt from " & SCRIPT_NAME & " after CR"
                    End If
                Else
                    ' Check for devices that have no VTY sessions available and therefore log you straight in
                    If Right(cl.RxBuffer, Len(DEVICE_STANDARDPROMPT)) = DEVICE_STANDARDPROMPT Then
                        ' No sessions were available, but we have been logged in
                        cl.Log 4, "No password was required to login to " & SCRIPT_NAME
                    Else
                        ' Login failed - report the results
                        If cl.CurDevLoginUsesAAA = "1" Then
                           cl.Log 1, "Did not receive Login entry prompt from " & SCRIPT_NAME
                        Else
                           cl.Log 1, "Did not receive VTY entry prompt from " & SCRIPT_NAME
                        End If
                    End If
                End If
            Case 1 ' Username prompt received - do a username and password login
                If LoginAAA = True Then LoginTelnet = True
            Case 2 ' Password prompt received - do a password only login
                 If SendPassword("LOGINVTY") = True Then LoginTelnet = True
            Case 4, 5 ' Logged in with no authentication
                 cl.Log 4, "No VTY password was required to login to " & SCRIPT_NAME
            End Select
        Loop
       
    End Function


    Function LoginAAA()
    ' The Function LoginAAA() is called when authenticating to a device using AAA/TACACS/RADIUS or Local username/password authentication.
    '
    ' Calls On:         SendUsername
    '                   SendPassword
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
        ' Declare variables
        Dim iLoginAttempts
       
        ' Default function return value
        LoginAAA = False
       
        cl.Log 4, "Beginning LoginAAA"
       
        ' Try 3 times to log in - sometimes RADIUS sends failure with correct data due to inability to handle multiple simutaneous login requests
        For iLoginAttempts = 1 To 3
            If SendUsername("LOGINAAA") = True Then
                ' Login was successful, so now send password
                If SendPassword("LOGINAAA") = True Then
                    ' Password accepted, we are authenticated
                    LoginAAA = True
                    Exit For
                Else
                    ' Authentication failed after sending password
                    cl.Log 2, "LoginAAA authentication failed - will retry"
                    ' Pause for 3 seconds
                    cl.Delay 3
                End If
            Else
                ' No password prompt received after sending username to device
                ' Check the last character of what the receive buffer
                If Len(cl.RxBuffer) > 0 Then
                    If Mid(cl.RxBuffer, Len(cl.RxBuffer) - Len(DEVICE_STANDARDPROMPT) + 1) = DEVICE_STANDARDPROMPT Or _
                       Mid(cl.RxBuffer, Len(cl.RxBuffer) - Len(DEVICE_PRIVILEGEDPROMPT) + 1) = DEVICE_PRIVILEGEDPROMPT Then
                        ' A device prompt was received, so assume no password was needed to authenticate
                        LoginAAA = True
                        Exit For
                    Else
                        ' Something other then device prompts was received - retry
                    End If
                End If
                ' We received something unknown - retry
                cl.Log 2, "LoginAAA username failed - will retry"
            End If
        Next

    End Function


    Function LoginSSH()
    ' The Function LoginSSH() is called when authenticating to a device using SSH.
    '
    ' Calls On:         LoginAAA
    '                   SendPassword
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
    ' For SSH login:
    ' Username and Password are compulsory but the values are encoded as part of the protocol, so all we do is wait.
    ' Once the connection is established we should get the prompt in the response buffer.
       
        ' Declare variables
        Dim rgMult
        Dim iRetVal
        Dim bSentCR
        Dim bStillProcessing
      
       
        ' Default function return value
        LoginSSH = False
       
        cl.Log 4, "LoginSSH waiting for command prompt"
            
        ' Redimension rgMult to number of response items we are testing for (increment accordingly when adding new values)
        ReDim rgMult(4)
      
        ' Expected possible default return values in order we want to test for them
        rgMult(1) = DEVICE_STANDARDPROMPT
        rgMult(2) = DEVICE_PRIVILEGEDPROMPT
        rgMult(3) = DEVICE_USERNAMEPROMPT
        rgMult(4) = DEVICE_PASSWORDPROMPT
        
        ' Default the variables
        bSentCR = False
        bStillProcessing = True
       
        Do While bStillProcessing
            ' Only loop back if instructed to do so
            bStillProcessing = False
       
            iRetVal = cl.WaitForMultData(rgMult, , COMMAND_TIMEOUT)
       
            Select Case iRetVal
            Case 0
                ' Check if response buffer is empty, then send a <CR> to try 'wake' the device up - *NOTE: only try this once
                If Len(cl.RxBuffer) = 0 Then
                    If bSentCR = False Then
                        cl.SendData vbCr
                        bSentCR = True
                        bStillProcessing = True
                    Else
                        cl.Log 1, "Did not receive command prompt after connecting via SSH after CR"
                    End If
                Else
                    cl.Log 1, "Did not receive command prompt after connecting via SSH"
                End If
            Case 1, 2
                ' A device prompt has been received - Login SSH successful
                LoginSSH = True
            Case 3
                ' We received a username prompt - go through the AAA login
                LoginSSH = LoginAAA
            Case 4
                ' We received a password prompt after SSH login - go through a VTY login
                LoginSSH = SendPassword("LOGINVTY")
            End Select
        Loop

    End Function


    Function LoginCV(sConnectTo, sConnectFrom)
        Call cl.CatToolsNoSupport
    End Function


    Function LoginCVSSH()
        Call cl.CatToolsNoSupport
    End Function


    Function SendPassword(sWhichPassword)
    ' The Function SendPassword() is called when a password prompt is received from the device.
    ' It sends the relevant password from the device setup information to the device and waits for the response.
    '
    ' Calls On:         N/A
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
       
        ' Declare variables
        Dim rgMult
        Dim iRetVal
       
        ' Default function return value
        SendPassword = False
       
        ' Redimension rgMult to number of response items we are testing for (increment accordingly when adding new values)
        ReDim rgMult(5)
       
        ' Expected possible default return values in order we want to test for them
        rgMult(1) = DEVICE_PASSWORDPROMPT
        rgMult(2) = "Login incorrect"
        'rgMult(3) = ... add additional rgMults if required

        ' *NOTE: Set device prompts last
        rgMult(4) = DEVICE_STANDARDPROMPT
        rgMult(5) = DEVICE_PRIVILEGEDPROMPT
       
        ' Flush the response buffer
        cl.FlushRxBuffer
           
        ' Send the relevant password
        Select Case sWhichPassword
        Case "LOGINVTY"
            ' Override default VTY Password prompt if required (i.e. custom VTY prompt set in device setup - Prompts tab)
            If Len(cl.CurDevVTYPrompt) > 0 Then rgMult(1) = cl.CurDevVTYPrompt
            cl.Log 4, "Sending login VTY password"
            cl.SendData cl.CurDevVTYPass & vbCr
        Case "LOGINAAA"
            ' Override default if required (i.e. custom Password prompt set in device setup - Prompts tab)
            If Len(cl.CurDevAAAPassPrompt) > 0 Then rgMult(1) = cl.CurDevAAAPassPrompt
            cl.Log 4, "Sending login AAA password"
            cl.SendData cl.CurDevAAAPassword & vbCr
        Case "ENABLEVTY"
            ' Override default if required (i.e. custom Enable prompt set in device setup - Prompts tab)
            If Len(cl.CurDevEnablePrompt) > 0 Then rgMult(1) = cl.CurDevEnablePrompt
            cl.Log 4, "Sending enable password"
            cl.SendData cl.CurDevEnablePass & vbCr
        Case "ENABLEAAA"
            ' Override default if required (i.e. custom Password prompt set in device setup - Prompts tab)
            If Len(cl.CurDevAAAPassPrompt) > 0 Then rgMult(1) = cl.CurDevAAAPassPrompt
            cl.Log 4, "Sending enable AAA password"
            cl.SendData cl.CurDevAAAPassword & vbCr
        Case Else
            cl.Log 4, "Did not know which password to send"
            Exit Function
        End Select
               
        ' Compare device response buffer to our response array (rgMult)
        iRetVal = cl.WaitForMultData(rgMult, , COMMAND_TIMEOUT)
        Select Case iRetVal
            Case 1, 2
                ' Failed - invalid password, or password prompt received back from device
                cl.Log 1, "Password is incorrect for device"
            Case 4, 5
                ' Login accepted - a valid device prompt was received back
                SendPassword = True
            Case Else
                ' Unexpected response received back from device
                cl.Log 1, "Did not receive expected response after sending password"
        End Select

    End Function


    Function SendUsername(sWhichUsername)
    ' The Function SendUsername() is called when a username prompt is received from the device.
    ' It sends the username from the device setup information to the device and waits for the response.
    '
    ' Calls On:         N/A
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
       
        ' Declare variables
        Dim rgMult
        Dim iRetVal
       
        ' Default function return value
        SendUsername = False
       
        ' Redimension rgMult to number of response items we are testing for (increment accordingly when adding new values).
        ReDim rgMult(5)
       
        ' Expected possible default return values in order we want to test for them
        rgMult(1) = DEVICE_PASSWORDPROMPT
        rgMult(2) = DEVICE_USERNAMEPROMPT
        'rgMult(3) = ... add additional rgMults if required.

        ' Set additional rgMults depending on which username we are sending
        Select Case sWhichUsername
        Case "LOGINAAA"  ' Initial login
            cl.Log 4, "Sending login AAA username"
            ' Failed responses when doing an initial AAA login
            rgMult(3) = "% Login invalid"
            rgMult(4) = "% Authentication failed"
        Case "ENABLEAAA"  ' Privileged username
            cl.Log 4, "Sending enable AAA username"
            ' Failed responses when entering enable mode
            rgMult(3) = "Login invalid"
            rgMult(4) = "Access denied"
            rgMult(5) = "Error in authentication"
        Case Else  ' Input parameter not specified or not an expected value
            cl.Log 4, "Missing or invalid username input parameter specified"
            Exit Function
        End Select
       
        ' Override defaults if required (i.e. custom Password and Username prompts set in device setup - Prompts tab)
        If Len(cl.CurDevAAAPassPrompt) > 0 Then rgMult(1) = cl.CurDevAAAPassPrompt
        If Len(cl.CurDevAAAUserPrompt) > 0 Then rgMult(2) = cl.CurDevAAAUserPrompt
           
        ' Flush the buffer
        cl.FlushRxBuffer
       
        ' Send Username and wait for response
        cl.SendData cl.CurDevAAAUsername & vbCr
       
        ' Compare device response buffer to our response array (rgMult)
        iRetVal = cl.WaitForMultData(rgMult, , COMMAND_TIMEOUT)

        ' The desired result is to get a password prompt back after sending username
        If iRetVal = 1 Then  ' i.e. rgMult(1) value - DEVICE_PASSWORDPROMPT
            SendUsername = True
        End If
       
    End Function


    Function DetermineHostname()
    ' The Function DetermineHostname() is called to establish and set the following values used as anchor points after a
    ' command has been sent and its output or response received:
    '   cl.DeviceHostnameID        -  the host name of the device
    '   cl.DeviceVTYPrompt         -  the host name and ending with DEVICE_STANDARDPROMPT
    '   cl.DeviceEnablePrompt      -  the host name and ending with DEVICE_PRIVILEGEDPROMPT
    '   cl.DeviceConfigPrompt      -  the host name and ending with DEVICE_CONFIGPROMPT
    '
    ' Calls On:         N/A
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
        DetermineHostname = cl.DetermineHostname(DEVICE_STANDARDPROMPT, DEVICE_PRIVILEGEDPROMPT, DEVICE_CONFIGPROMPT)
       
    End Function


    Function SendPostLoginCommands()
    ' The Function SendPostLoginCommands() is called to issue CLI commands setting the environment post successful login.
    ' Refer to Function SendPostEnterEnableModeCommands() for examples of the type of code you would enter.
    '
    ' Calls On:         N/A
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)

        SendPostLoginCommands = True

    End Function


    Function SendPostEnterEnableModeCommands()
    ' The Function SendPostEnterEnableModeCommands() is called to issue CLI commands setting the environment after successfully entering Enable mode.
    ' Below are two examples of the code to disable paging of the command output (i.e. the --More-- prompts)
    '
    ' Calls On:         N/A
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
       
    ' #Example 1:
    ' Sends the command to disable paging if set as constant COMMAND_DISABLEPAGING.
    ' If the command fails for any reason the function just continues and returns TRUE
    '
        If Len(COMMAND_DISABLEPAGING) > 0 Then
            cl.SendAndWaitForPrompt (COMMAND_DISABLEPAGING)
        End If
       
        SendPostEnterEnableModeCommands = True
       
       
    ' #Example 2:
    ' Sends the command to disable paging if set as constant COMMAND_DISABLEPAGING.
    ' If the command fails for any reason the function returns FALSE, else if command is successful or command is not to be issued then returns TRUE
    '
    '    If Len(COMMAND_DISABLEPAGING) > 0 Then
    '        SendPostEnterEnableModeCommands = cl.SendAndWaitForPrompt(COMMAND_DISABLEPAGING) ' TRUE if command successful; FALSE if not (invalid command / privileged level doesn't allow, etc)
    '    Else ' No command to send so return TRUE
    '        SendPostEnterEnableModeCommands = True
    '    End If

    End Function


    Function SendPreExitEnableModeCommands()
    ' The Function SendPreExitEnableModeCommands() is called to issue CLI commands resetting the environment before attempting to exit Enable mode.
    ' Below are two examples of the code to re-enable paging of the command output
    '
    ' Calls On:         N/A
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
       
    ' #Example 1:
    ' Sends the command to re-enable paging if set as constant COMMAND_ENABLEPAGING.
    ' If the command fails for any reason the function just continues and returns TRUE
    '
        If Len(COMMAND_ENABLEPAGING) > 0 Then
            cl.SendAndWaitForPrompt (COMMAND_ENABLEPAGING)
        End If
        SendPreExitEnableModeCommands = True
       
       
    ' #Example 2:
    ' Sends the command to re-enable paging if set as constant COMMAND_ENABLEPAGING.
    ' If the command fails for any reason the function returns FALSE, else if command is successful or command is not to be issued then returns TRUE
    '
    '    If Len(COMMAND_ENABLEPAGING) > 0 Then
    '        SendPreExitEnableModeCommands = cl.SendAndWaitForPrompt(COMMAND_ENABLEPAGING) ' TRUE if command successful; FALSE if not (invalid command / privileged level doesn't allow, etc)
    '    Else ' No command to send so return TRUE
    '        SendPreExitEnableModeCommands = True
    '    End If

    End Function


    Function SendSessionTerminationCommands()
    ' The Function SendSessionTerminationCommands() is called to issue CLI commands to reset the environment at session end.
    '
    ' Calls On:         ExitConfigMode
    '                   SendPreExitEnableModeCommands
    '                   ExitEnableMode
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
        ' Call function to exit configuration mode if currently in
        ExitConfigMode
       
        ' Call function to exit enable mode
        ExitEnableMode
       
        ' Now send the exit session command
        If Len(COMMAND_DISCONNECT) > 0 Then
            cl.Log 4, "Disconnecting from " & cl.CurDevName
            cl.SendData COMMAND_DISCONNECT & vbCr
        End If
       
    End Function


    Function EnterEnableMode()
    ' The Function EnterEnableMode() will attempt to enter priviledged or Enable mode.
    '
    ' Calls On:         EnterEnableModeVTY
    '                   EnterEnableModeAAA
    '                   SendPostEnterEnableModeCommands
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
        ' Declare variables
        Dim rgMult
        Dim iRetVal
        Dim sCmd
       
        ' Default response
        EnterEnableMode = False
      
        If Len(COMMAND_ENTERENABLEMODE) = 0 Then
            ' The COMMAND_ENTERENABLEMODE constant not set as the device does not have an Enable mode. Return TRUE.
            EnterEnableMode = True
        Else
            ' Check and see if we are already in Enable mode before trying to go there
            iRetVal = CurrentDeviceContextLevel
            ' 1 = VTY prompt, 2 = Enable prompt, 3 = Config prompt, 0 = Unknown prompt
     
            If (iRetVal = 0) Or (iRetVal = 1) Then
                ' We are at the VTY prompt.  Issue the command to get us into Enable mode
                cl.Log 4, "Entering Enable mode"
           
                ' Default return value and clear the response buffer
                EnterEnableMode = False
                cl.FlushRxBuffer
               
                ' Command to send
                sCmd = COMMAND_ENTERENABLEMODE
               
                ' If device setup specifies a priviledged level, then append to the Enable command (e.g. "Enable 15"),
                If Len(cl.CurDevPrivilegeLevel) > 0 Then
                    sCmd = sCmd & " " & cl.CurDevPrivilegeLevel
                End If
               
                ' Type in command and wait for echo
                iRetVal = cl.SendAndWaitForEcho(sCmd)
               
                ' Was command echoed back from the device, if not then Exit
                If iRetVal = False Then Exit Function
               
                ' Command echoed so flush the response buffer ready for command response data
                cl.FlushRxBuffer
               
                ' Send CR to send the command
                cl.SendData vbCr
               
                cl.Log 4, "Waiting for Enable mode password prompt"
                   
                ' Redimension rgMult to number of response items we are testing for (increment accordingly when adding new values)
                ReDim rgMult(4)
      
                ' Expected possible default return values in order we want to test for them
                rgMult(1) = cl.DeviceEnablePrompt
                rgMult(2) = cl.DeviceVTYPrompt
                rgMult(3) = DEVICE_PASSWORDPROMPT
                rgMult(4) = DEVICE_USERNAMEPROMPT
               
                ' Override defaults if required (i.e. custom prompts set in device setup - Prompts tab)
                If Len(cl.CurDevEnablePrompt) > 0 Then rgMult(3) = cl.CurDevEnablePrompt
                If Len(cl.CurDevAAAUserPrompt) > 0 Then rgMult(4) = cl.CurDevAAAUserPrompt
               
                ' Analyse the response data from the device after sending the command
                iRetVal = cl.WaitForMultData(rgMult, , COMMAND_TIMEOUT)
               
                Select Case iRetVal
                Case 0 ' No valid data received
                     If cl.CurDevEnableUsesAAA = "1" Then
                        cl.Log 1, "Did not receive expected Username prompt when entering Enable mode"
                     Else
                        cl.Log 1, "Did not receive expected prompt when entering Enable mode"
                     End If
                     Exit Function
                Case 1 ' No Enable password was set or we've got custom Enable prompt
                     cl.Log 4, "Already in Enable mode, or no password was set"
                Case 2 ' unable to enter Enable mode
                     cl.Log 1, "Failed to enter Enable mode"
                     Exit Function
                Case 3, 5 ' Enable password prompt received
                     If EnterEnableModeVTY = False Then Exit Function
                Case 4 ' Username prompt received
                     If EnterEnableModeAAA = False Then Exit Function
                End Select
               
                EnterEnableMode = True
                cl.Log 4, "Entered Enable mode OK"
            Else
                ' We were already in Enable or Config mode
                cl.Log 4, "Skipping enter Enable mode as we are already in Enable mode"
                EnterEnableMode = True
            End If
        End If
        ' Call function to set the environment before exiting enable mode
        SendPostEnterEnableModeCommands
       
    End Function


    Function EnterEnableModeAAA()
    ' The Function EnterEnableModeAAA() requires Username and Password to enter Enable mode.
    ' The command has been sent to enter Enable mode and we have received the Username (or equivilent) prompt.
    '
    ' Calls On:         SendUsername
    '                   SendPassword
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
        EnterEnableModeAAA = False
       
        ' Send the username as specified in the settings
        If SendUsername("ENABLEAAA") Then
            If SendPassword("ENABLEAAA") Then
                EnterEnableModeAAA = True
            End If
        End If
    End Function


    Function EnterEnableModeVTY()
    ' The Function EnterEnableModeVTY() requires just Password to enter Enable mode.
    ' The command has been sent to enter Enable mode and we are at the password prompt.
    '
    ' Calls On:         SendPassword
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
        ' Send the password as specified in the settings
        If cl.CurDevEnableUsesAAA = "1" Then
           EnterEnableModeVTY = SendPassword("ENABLEAAA")
        Else
           EnterEnableModeVTY = SendPassword("ENABLEVTY")
        End If
       
    End Function


    Function ExitEnableMode()
    ' The Function ExitEnableMode() will attempt to exit priviledged or Enable mode.
    '
    ' Calls On:         SendPreExitEnableModeCommands
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)

        ' Declare variables
        Dim iRetVal
       
        ' Default response
        ExitEnableMode = False

        If Len(COMMAND_EXITENABLEMODE) = 0 Then
            ' The COMMAND_EXITENABLEMODE constant not set as the device does not have an Enable mode. Return TRUE.
            ExitEnableMode = True
        Else
            ' Check and see if we are in Enable mode before trying to exit from it
            iRetVal = CurrentDeviceContextLevel
            ' 1 = VTY prompt, 2 = Enable prompt, 3 = Config prompt, 0 = Unknown prompt

            If iRetVal = 2 Then
                ' We are in enable mode, so call function to reset the environment before exiting enable mode
                SendPreExitEnableModeCommands
               
                cl.Log 4, "Exiting enable mode"
                ' Send command to exit out of Enable mode
                cl.SendAndWaitForPrompt COMMAND_EXITENABLEMODE
                ' Check the context level again to ensure we are out of Enable mode
                If CurrentDeviceContextLevel = 1 Then
                    ' Exited OK, so return TRUE
                    ExitEnableMode = True
                    cl.Log 4, "Exited enable mode OK"
                End If
            End If
           
        End If
       
    End Function


    Function EnterConfigMode()
    ' The Function EnterConfigMode() will attempt to enter Configuration mode.
    '
    ' Calls On:         SendCommandSingle
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
     
      
        ' Declare variables
        Dim iRetVal
       
        ' Default response
        EnterConfigMode = False
       
        ' Check to see if we not in VTY mode or already in Config mode before trying to enter it
        iRetVal = CurrentDeviceContextLevel
        ' 1 = VTY prompt, 2 = Enable prompt, 3 = Config prompt, 0 = Unknown prompt

        Select Case iRetVal
        Case 0, 2
            ' Check the COMMAND_ENTERCONFIG constant has been set
            If Len(COMMAND_ENTERCONFIG) > 0 Then
                ' Attempt to enter Config mode.  A level 1 error raised if not entered ok
                If SendCommandSingle(COMMAND_ENTERCONFIG, 0, 1, 0) Then
                    ' Verify we have entered Config mode OK
                    If CurrentDeviceContextLevel = 3 Then
                        EnterConfigMode = True
                    End If
                End If
            Else
                ' No value set for the COMMAND_ENTERCONFIG constant, so skip trying to enter.  Assume this is not needed and Return TRUE
                cl.Log 4, "Skipping enter Config mode"
                EnterConfigMode = True
            End If
        Case 1
            ' We are still in VTY mode - Return FALSE
            cl.Log 4, "Can't enter Config mode while in VTY mode"
        Case 3
            ' WE are already in Config mode - Return TRUE
            cl.Log 4, "Already in Config mode"
            EnterConfigMode = True
        End Select
       
    End Function
          

    Function ExitConfigMode()
    ' The Function ExitConfigMode() will attempt to exit Configuration mode.
    '
    ' Calls On:         N/A
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
        ' Declare variables
        Dim iRetVal
        Dim iCount
        Dim iMaxRetries
        Dim sCmd
       
        ' Default response
        ExitConfigMode = True
       
        If Len(COMMAND_EXITCONFIG) = 0 Then
            ' The COMMAND_EXITCONFIG constant was not set, so assume the device does not have a Config mode
        Else
            ' Initialise variables
            iCount = 0
            iMaxRetries = 5
           
            ' Check and see if we are in Config mode before trying to exit from it
            iRetVal = CurrentDeviceContextLevel
            ' 1 = VTY prompt, 2 = Enable prompt, 3 = Config prompt, 0 = Unknown prompt
           
            Select Case iRetVal
            Case 3
                ' We are at the Config mode prompt
                cl.Log 4, "Exiting config mode"
                sCmd = COMMAND_EXITCONFIG
                If sCmd = "CTRL-Z" Then sCmd = Chr(26)
               
                ' Loop sending the command up to number of Attempts specified.
                ' This is used to try exit back to the Enable mode, when we have navigated down the depths of Config mode levels
                Do While (iRetVal = 3) And iCount <= iMaxRetries
                    iCount = iCount + 1
                    cl.SendData sCmd
                    ' Re-evaluate the current context level to see if we are still at a Config prompt
                    iRetVal = CurrentDeviceContextLevel
                Loop
                ' We have exceeded the maximum retry limit, so Return FALSE (failed to exit config mode successfully)
                If iCount > iMaxRetries Then ExitConfigMode = False
               
                ' We are back at Enable mode - Return TRUE
                If iRetVal = 2 Then cl.Log 4, "Exited Config mode ok"
           
            Case Else
                ' We were not in Config mode so it wasn't necessary to try exit it
            End Select
       
        End If
       
    End Function
     

    Function CurrentDeviceContextLevel()
    ' The Function CurrentDeviceContextLevel() is called by a number of functions within the script to determine
    ' in which mode the device is currently in.  Normally it is called before sending a command to change to a different mode.
    ' The function returns a number identifying the current mode by examining the device prompt.
    '
    ' Calls On:         N/A
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
        ' Declare variables
        Dim rgMult(4)
        Dim iRetVal
       
        ' Flush the response buffer and send a <CR> and see what sort of prompt we get.
        ' This ensures we have a clean buffer with just the prompt in it to then examine
        cl.FlushRxBuffer
        cl.SendData vbCr

        ' Set the possible modes we could be in.
        '*Note: if the device VTY and Enable prompts are the same, it will return the 1st one in the rgMult list below, in this case VTY.
        rgMult(1) = cl.DeviceVTYPrompt
        rgMult(2) = cl.DeviceEnablePrompt
        rgMult(3) = cl.DeviceConfigPrompt
        rgMult(4) = "(config-" ' Config mode prompt. Sometimes used when long hostname prompts are truncated (e.g. "MyCiscoHostna(config-if-range)#")
       
        ' Evaluate the returned data
        iRetVal = WaitForMultData(rgMult, , COMMAND_TIMEOUT)
       
        If iRetVal = 4 Then iRetVal = 3   '3 and 4 are both config mode
       
        ' Return the mode
        CurrentDeviceContextLevel = iRetVal
       
    End Function


    Function GetConfig(sCmd, sStoredConfig)
    ' The Function GetConfig() sends a command (sCmd) to capture the device configuration and returns a
    ' text string (sStoredConfig).
    '
    ' Calls On:         SendCommandSingle
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
     

        ' Default function return status
        GetConfig = "Failed"
           
        ' Clear the response buffer
        cl.FlushRxBuffer

        ' Send the command to capture the configuration
        If SendCommandSingle(sCmd, 0, 1, 1) = True Then
           
            ' Copy the results of the command from the response buffer to the variable
            sStoredConfig = cl.RxBuffer
           
            ' Massage the device output:
            '  remove nulls
            sStoredConfig = cl.ReplaceText(sStoredConfig, Chr(0), "")
            '  Check if the DEVICE_CONFIGHEADERTEXT constant has been set
            If Len(DEVICE_CONFIGHEADERTEXT) > 0 Then
                ' Check output for header text and if found remove everything up to and including it
                If cl.TextInText(sStoredConfig, DEVICE_CONFIGHEADERTEXT) Then
                    sStoredConfig = cl.TextRemoveTextUpTo(sStoredConfig, DEVICE_CONFIGHEADERTEXT, True)
                End If
            End If
            '  remove padding
            sStoredConfig = Trim(sStoredConfig)
            '  remove blank header lines
            sStoredConfig = cl.TextRemoveBlankHeaderLines(sStoredConfig)
           
            ' Output capture and massage successful.  Set the function return status.
            GetConfig = "OK"
       
        End If
       
    End Function


    Function SendCommandSingle(sCmd, bYesToConfirm, iErrorLevel, bCleanBuffer)
    ' The Function SendCommandSingle() sends a command (sCmd) to the device and returns True if command
    ' executed successfully, False if not.
    '
    '   sCmd:           a string value being the command to send to the device.
    '   bYesToConfirm:  boolean value.
    '                   True: a Y (or Yes) will be sent if yes/no prompts are encountered.
    '                   False: a N (or No) will be sent if yes/no prompts are encountered.
    '   iErrorLevel:    is the level of error to raise if the command fails to execure successfully.
    '                   0 will not raise an error.
    '   bCleanBuffer:   boolean value.
    '                   True: the buffer will be returned with just the results of the command, i.e. prompts and commands trimmed from output.
    '                   False: the buffer will be left alone, returning the prompts and commands sent.
    '                   *NOTE: "--More--" 'paging' prompts will always be trimmed.
    '
    ' Calls On:         N/A
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
        ' Declare variables
        Dim rgMult
        Dim iRetVal
        Dim sStoredBuffer
        Dim bCommandExecutedOK
        Dim iTimeoutMultiplier
        Dim sStart 'start position for any data massaging
       
        ' Default function return value
        bCommandExecutedOK = False
       
        ' Set environment variables
        sStoredBuffer = ""
        iTimeoutMultiplier = 1

        ' Redimension rgMult to number of response items we are testing for.
        ReDim rgMult(10)
       
        ' Expected possible default return values in order we want to test for them
        rgMult(1) = DEVICE_MORETEXT
        rgMult(2) = DEVICE_INVALIDCOMMAND
        rgMult(3) = DEVICE_INCOMPLETECOMMAND
        rgMult(4) = DEVICE_YESNOTEXT
        rgMult(5) = vbcrlf & trim(cl.DeviceVTYPrompt) & chr(32) & vbcrlf      
        rgMult(6) = "!# End of configuration file. Press Enter to continue."

       
        ' *NOTE: the device prompts need to be checked for last, as the WaitForMultData() exits on finding the first matching rgMult.
        ' We therefore need to check the output for all the errors or other possible responses first before the device prompts as a
        ' device prompt will nearly always occur at the end of the device response, whether the response is the expected output or
        ' an error or invalid command type message.
        rgMult(8) = cl.DeviceVTYPrompt
        rgMult(9) = cl.DeviceEnablePrompt
        rgMult(10) = cl.DeviceConfigPrompt
        
        ' Clear the response buffer
        cl.FlushRxBuffer
       
        ' Check if we are sending a Chr(26) command (i.e. Ctrl-Z)
        If sCmd = Chr(26) Or cl.WaitForEcho = False Then ' do not do a wait for echo of Ctrl-Z command, as we are sending to the device Chr(26) and device echos ^Z which will cause the SendAndWaitForEcho function to report a failure
            cl.SendData sCmd
        Else ' Send the command to the device and wait for an echo back of the command
            If cl.SendAndWaitForEcho(sCmd) = False Then ' Echo not received
                cl.Log 4, "Did not receive echo of " & sCmd
                Exit Function
            End If
        End If
       
        ' Make final timeout value adjustments for specific commands that take longer to complete sending back the output data
        ' By default the timeout is preset at 30 seconds.
        ' Examples:
        'If LCase(Left(sCmd, 9)) = "show tech" Then iTimeoutMultiplier = 5
        'If LCase(Left(sCmd, 14)) = "show interface" Then iTimeoutMultiplier = 3

        ' Send a message to Info Log pane showing timeout is being increased
        If iTimeoutMultiplier > 1 Then
            cl.Log 4, "Increasing timeout for next command only"
        End If
           
        ' Clear out response buffer again to remove any previous captured data text (i.e. the command text sent) if bCleanBuffer input parameter is set to True
        If bCleanBuffer Then cl.FlushRxBuffer
       
        ' Now send <CR> to execute the command on the device
        cl.SendData vbCr
                   
        ' Check the device response and process the results
        cl.Log 4, "Waiting for a response to: " & sCmd
        Do
            ' Wait for a response from the device
            iRetVal = cl.WaitForMultData(rgMult, , COMMAND_TIMEOUT * iTimeoutMultiplier)
           
            ' Store the response
            sStoredBuffer = sStoredBuffer & cl.RxBuffer
            ' Analyse the results
            Select Case iRetVal
            Case 0
                ' No valid data received
                If iErrorLevel > 0 Then
                    cl.Log iErrorLevel, "Did not receive expected response to command: " & sCmd
                End If
                Exit Do
            Case 1
                ' Handle the --more-- paging prompt.  Send space to advance to next page
                cl.FlushRxBuffer
                cl.SendData " "
            Case 2
                ' Invalid command - error with syntax
                If iErrorLevel > 0 Then
                    cl.Log iErrorLevel, "Error with syntax: " & sCmd
                End If
                Exit Do
            Case 3
                ' Incomplete command
                If iErrorLevel > 0 Then
                    cl.Log iErrorLevel, "Error with command: " & sCmd
                End If
                Exit Do
            Case 4
                ' yes/no (y/n) prompt
                cl.Log 4, "Y/N encountered"
                cl.FlushRxBuffer
                ' Send 'y' or 'n' depending on bYesToConfirm input parameter value
                If bYesToConfirm Then
                    cl.Log 4, "Sending Y"
                    cl.SendData "y" & vbCr
                Else
                    cl.Log 4, "Sending N"
                    cl.SendData "n" & vbCr
                End If
            Case 5
                'do nothing - ignore undesired echoed hostname prompt found at top of script (do not exit the loop)
                cl.Log 4, "Ignoring initial hostname prompt"
                cl.FlushRxBuffer
            Case 6
                cl.Log 4, "End of Config file detected"
                cl.FlushRxBuffer
                cl.SendData vbCr
            Case 8, 9, 10
                ' Command executed successfully and device prompt received back.  Set the function return value
                bCommandExecutedOK = True
               
                ' Massage data before returning, if requested
                If bCleanBuffer Then
                    ' Trim off device prompt from end of response data if bCleanBuffer input parameter setto True
                    sStart = InStrRev(sStoredBuffer, rgMult(iRetVal))
                    If sStart > 0 Then sStoredBuffer = Mid(sStoredBuffer, 1, sStart - 1)
                End If
                Exit Do
            End Select
        Loop
       
        ' Final massage of response data before returning to CatTools
        If Len(DEVICE_MORETEXT) > 0 Then  ' Remove any --more-- paging prompts
            ' Use this next line to remove the whole line of output
            'sStoredBuffer = cl.TextRemoveLinesContainingText(sStoredBuffer, DEVICE_MORETEXT)
            ' ...or use this to replace the just the matching text within the line
            'sStoredBuffer = cl.ReplaceText(sStoredBuffer, DEVICE_MORETEXT, "")
        End If
       
        ' Return the data and send function return value
        cl.RxBuffer = sStoredBuffer
        SendCommandSingle = bCommandExecutedOK

    End Function


    Function SendCommandsMultiple(sCmdList, sCapturedDataFile, bYesToConfirm, bStopOnErrors, iNumCommands, iNumSuccess, iNumErrors)
    ' The Function SendCommandsMultiple() sends a series of commands (sCmdList) to the device and returns True if ALL commands
    ' were executed successfully, False if not.
    ' It also passes back information through the three returned iNum variables:
    '
    '   iNumCommands:   Used to return to the calling function the number of commands executed in total
    '   iNumSuccess:    Used to return to the calling function the number of commands succesfully executed
    '   iNumErrors:     Used to return to the calling function the number of commands unsuccesfully executed
    '
    ' Calls On:         SendCommandSingle
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
        ' Declare variables
        Dim iRetVal
        Dim rgCommandList
        Dim sCmd
        Dim iCount ' loop counter
        Dim sClientResultsFile
       
        ' Default function return value
        SendCommandsMultiple = True
       
        ' Set environment variables
        sCmd = ""
        iNumCommands = 0
        iNumSuccess = 0
        iNumErrors = 0
        iCount = 0
       
        ' Evaluate the commands
        rgCommandList = Split(sCmdList, vbCrLf)
        iNumCommands = UBound(rgCommandList)
        If iNumCommands = -1 Then Exit Function
       
        ' Send the commands
        Do
            sCmd = rgCommandList(iCount)

            ' Check whether command to send is a database Meta command, in which case do not send to device
            iRetVal = cl.DBMetaCmd(sCmd)
           
            If iRetVal = 0 Then
            ' Command is not a database Meta command so check whether command is a utility Meta command, in which case do not send to device
                iRetVal = cl.UtilityMetaCmd(sCmd)
            End If

           
            Select Case iRetVal
            Case 0 ' Not a meta command so send command to device and check if successful
                If SendCommandSingle(sCmd, bYesToConfirm, 2, False) Then
                    iNumSuccess = iNumSuccess + 1
                    ' Store output if required
                    If Len(sCapturedDataFile) > 0 Then
                        cl.LogToFile sCapturedDataFile, cl.RxBuffer, 1
                       
    '<*** The next block of code will only run with CatTools versions later than v3.2.19.  Do not uncomment if running 3.2.19 or prior as this will cause an error.
    '                    ' Check the activity to see if the output of the command(s) should be emailed
    '                    If cl.DBCheckScheduleOption(cl.ScheduleNumber, 8) = 1 Then
    '                       ' Write the output to a temporary file in the ClientTemp folder
    '                        sClientResultsFile = cl.GetUniqueDeviceFileName("", "CLI")
    '                        cl.LogToFile sClientResultsFile, cl.RxBuffer, 1
    '                    End If
    '***>
                    End If
                    ' Clear the response buffer ready for the next command
                    cl.FlushRxBuffer
                Else ' Command not executed successfully
                    iNumErrors = iNumErrors + 1
                End If
            Case 1
                ' Command to send is a Meta command and processed ok
                iNumSuccess = iNumSuccess + 1
            Case -1
                ' Command is a Meta command and error occurred
                iNumErrors = iNumErrors + 1
            End Select
           
            ' Check for errors and abort if necessary
            If iNumErrors > 0 And bStopOnErrors = 1 Then
                cl.Log 1, "Aborting command entry due to command error"
                SendCommandsMultiple = False
                Exit Do
            End If
            ' Increment counter to send next command
            iCount = iCount + 1
           
        Loop Until iCount > iNumCommands
        iNumCommands = iNumCommands + 1
       

    End Function


    Function Activity_BackupRunningConfig(sAltCommand, sTempFile, sIgnoreText)
    ' The Function Activity_BackupRunningConfig() is the activity used to get the running configuration from the device.
    ' It calls the GetConfig() function to capture the configuration data, sets the text to ignore in the configuration when comparing
    ' to the last configuration backup file, and passes the capture and ignore text back to the main activity script in CatTools.
    '
    ' Calls On:         GetConfig
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
        
       
        ' Declcare
        Dim sCmd
        Dim sStoredConfig
        Dim rgIgnoreText() ' ignore text array
       
       
        If Len(sAltCommand) > 0 Then
            sCmd = sAltCommand
        Else
            sCmd = COMMAND_RUNNINGCONFIG
        End If

        Activity_BackupRunningConfig = GetConfig(sCmd, sStoredConfig)

        ' Set the configuration lines (or text within a line) that should be ignored by the compare process
        sIgnoreText = ""
       
        ReDim rgIgnoreText(3) ' ReDeclare the array with 4 elements (*NOTE: arrays are 0 based).  Increment if more ignore text elements are added
        rgIgnoreText(0) = "^" & "! last configuration change at"
        rgIgnoreText(1) = "^" & "! nvram config last updated at"
        rgIgnoreText(2) = "^" & "ntp clock-period"
        rgIgnoreText(3) = "<" & "! No configuration change since last restart"
        'rgIgnoreText(4) = "...add an instruction here" & "... and ignore text here"
        
        'Ignore instructions define the context of the ignore text.
        '   ^ is the instruction to ignore lines with the sample text occurring anywhere in them
        '   < is the instruction to ignore lines that begin with the sample text
        '   > is the instruction to ignore lines that end with the sample text
       
        ' Join the above ignore text array elements
        sIgnoreText = Join(rgIgnoreText, "|")

        cl.LogToFile sTempFile, sStoredConfig, 0
           
    End Function


    Function Activity_SendCommands(sCommandsToSend, sCapturedDataFile, bYesToConfirm, bStopOnErrors)
    ' The Function Activity_SendCommands() is called by the Device.CLI.Send commands main script to send one or a group of user defined commands to a device.
    ' It also passes back information through the three returned iNum variables:
    '
    '   iNumCommands:   Used to return the number of commands executed in total
    '   iNumSuccess:    Used to return the number of commands succesfully executed
    '   iNumErrors:     Used to return the number of commands unsuccesfully executed
    '
    ' Calls On:         SendCommandsMultiple
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
           
       
        ' Declare variables
        Dim iNumCommands
        Dim iNumSuccess
        Dim iNumErrors
       
        ' Default function return value
        Activity_SendCommands = ""

        ' Call on the function which sends each command separately and report on the success or failure ofthe command
        SendCommandsMultiple sCommandsToSend, sCapturedDataFile, bYesToConfirm, bStopOnErrors, iNumCommands, iNumSuccess, iNumErrors

        ' Update function return value with the commands execution outcome
        Activity_SendCommands = iNumSuccess & " of " & iNumCommands & vbTab & iNumErrors

    End Function


    Function Activity_ModifyConfig(sCommandsToSend, sCapturedDataFile, bYesToConfirm, bStopOnErrors, bDoSaveToNVRAM)
    ' The Function Activity_ModifyConfig() is called by the Device.CLI.Modify config main script to send one or a group of user defined commands to a device.
    ' The difference to Activity_SendCommands is that it enters config mode first and then has the ability to save changes to startup config when finished.
    ' It also passes back information through the three returned iNum variables:
    '
    '   iNumCommands:   Used to return the number of commands executed in total
    '   iNumSuccess:    Used to return the number of commands succesfully executed
    '   iNumErrors:     Used to return the number of commands unsuccesfully executed
    '
    ' Calls On:         SendCommandsMultiple
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
        ' Declare variables
        Dim iNumCommands
        Dim iNumSuccess
        Dim iNumErrors
        Dim bContinueWithSave ' flag to save configuration changes
        Dim sSaveResults
        Dim sCmd
       
        ' Default function return value and variables
        Activity_ModifyConfig = ""
        bContinueWithSave = True
       
        ' Call function to enter config mode
        If EnterConfigMode = False Then Exit Function
       
        ' Send the commands. Stop if a 'stop-on-error' was triggered
        If Not SendCommandsMultiple(sCommandsToSend, sCapturedDataFile, bYesToConfirm, bStopOnErrors, iNumCommands, iNumSuccess, iNumErrors) Then
            ' Reset the configuration change flag
            bContinueWithSave = False
        End If
       
        ' Set the command to exit config
        sCmd = COMMAND_EXITCONFIG
        If LCase(sCmd) = "ctrl-z" Then
            sCmd = Chr(26)
        End If
       
        ' Send command to exit config mode
        cl.SendData sCmd
        cl.Log 4, "Exiting config mode"
        ' Wait for confirmation of exiting config mode
        If cl.WaitForData(cl.DeviceEnablePrompt, COMMAND_TIMEOUT) = False Then
           cl.Log 1, "Failed to exit config mode"
           Exit Function
        End If

        ' Save to Startup if option selected in activity
        If bDoSaveToNVRAM Then
            ' Double check that no errors occurred when sending the commands
            If bContinueWithSave Then
                ' No errors, so call function to save the changes to startup configuration
                sSaveResults = SaveToNVRAM
            Else ' command execution error occurred
                cl.Log 2, "Copy running to startup skipped because StopOnError was selected"
            End If
        Else
            sSaveResults = "N/A"
        End If
      

        ' Update function return value with the commands execution outcome and results
        Activity_ModifyConfig = iNumSuccess & " of " & iNumCommands & vbTab & iNumErrors & vbTab & sSaveResults

    End Function


    Function SaveToNVRAM()
    ' The Function SaveToNVRAM() is called by Activity_ModifyConfig function if the activity option
    ' to save the running configuration changes to start-up config is selected.
    '
    ' Calls On:         N/A
    '
    ' Date Created:     [AutoGenDateScriptCreated]
    ' Modifications:    (Date - Description of changes)
       
       
        ' Declare variables
        Dim iRetVal
       
        If Len(COMMAND_SAVENVRAM) = 0 Then
            SaveToNVRAM = "Skipped"
        Else
            ' Make sure we are not still in config mode when attempting save
            ExitConfigMode
           
            ' Confirm we are at the Enable prompt before doing save
            iRetVal = CurrentDeviceContextLevel
            ' 1 = VTY prompt, 2 = Enable prompt, 3 = Config prompt
           
            If iRetVal = 2 Then
                cl.Log 4, "Saving running-config to startup-config"
                ' Send the command
                If SendCommandSingle(COMMAND_SAVENVRAM, 1, 1, 0) = False Then
                    ' Command failed
                    SaveToNVRAM = "Failed"
                Else ' Command OK
                    SaveToNVRAM = "OK"
                End If
               
            Else  ' Not at an Enable prompt
                SaveToNVRAM = "Cannot save to NVRAM as not currently in Enable mode"
            End If
       
        End If
       
    End Function


    Function Activity_InterDevicePing(sIPAddress)
        Call cl.CatToolsNoSupport
    End Function

    Function Activity_TFTPUpload(iActionType, sTFTPServer, sTFTPFile, sResponseFile, bDoSaveToNVRAM)
        Call cl.CatToolsNoSupport
        Activity_TFTPUpload = "Not supported"
    End Function

    Function Activity_UpdatePassword()
        Call cl.CatToolsNoSupport
    End Function

    Function Activity_Report_ARPTable(sAltCommand)
        Call cl.CatToolsNoSupport
    End Function

    Function Activity_Report_MACAddressTable(sAltCommand)
        Call cl.CatToolsNoSupport
    End Function

    Function Activity_Report_PortInfoTable(sAltCommand)
        Call cl.CatToolsNoSupport
    End Function

    Function Activity_Report_VersionTable(sAltCommand)
        Call cl.CatToolsNoSupport
    End Function

    Function Activity_Report_CDPNeighborsTable(sAltCommand, bHideDuplicateIP)
        Call cl.CatToolsNoSupport
    End Function

    Function Activity_Report_ErrorInfoTable()
        Call cl.CatToolsNoSupport
    End Function

    Function Activity_UpdateBanner(iBannerType, sDelimiter, sBannerText, sResponseFile, bDoSaveToNVRAM)
        Call cl.CatToolsNoSupport
        Activity_UpdateBanner = "Not supported"
    End Function

    Function Activity_Report_Compare_RunningStartup(sAltStartupCommand, sClientStartupFile, sAltRunningCommand, sClientRunningFile)
        Call cl.CatToolsNoSupport
    End Function

     

     

  • Hi Toosober,

    You could post the script and ini in a zip file on the thwack content exchange in the Kiwi CatTools custom device script section.

    With respect to the time stamp you should be able to get around this by using ignore text. In the Function 'Activity_BackupRunningConfig' function there is a section as outlined below and you should be able to add your own ignore text. You will need to redimension the array if you add additional items or replace the existing ignore text items with ones specific to your output;

        ' Set the configuration lines (or text within a line) that should be ignored by the compare process
        sIgnoreText = ""
       
        ReDim rgIgnoreText(3) ' ReDeclare the array with 4 elements (*NOTE: arrays are 0 based).  Increment if more ignore text elements are added
        rgIgnoreText(0) = "^" & "! last configuration change at"
        rgIgnoreText(1) = "^" & "! nvram config last updated at"
        rgIgnoreText(2) = "^" & "ntp clock-period"
        rgIgnoreText(3) = "<" & "! No configuration change since last restart"
        'rgIgnoreText(4) = "...add an instruction here" & "... and ignore text here"
        
        'Ignore instructions define the context of the ignore text.
        '   ^ is the instruction to ignore lines with the sample text occurring anywhere in them
        '   < is the instruction to ignore lines that begin with the sample text
        '   > is the instruction to ignore lines that end with the sample text
       
        ' Join the above ignore text array elements
        sIgnoreText = Join(rgIgnoreText, "|")

  • Thanks Wardini! Added the text at the beginning of the lines to rgIgnoreText( ) statements and it resolved the problem. I am now only getting "changed!" when there are actually changes. Also, I will post the zip file as you suggested, I am sure many other Avaya users will find it useful.

     

    Thanks again for your post!

  • No worries Toosober.

    Thanks for sharing.

    Kind regards,

    Gareth