• No results found

Tcl Example Used to Check for Interface Errors

In document Tcl Scripting for Cisco IOS (Page 115-121)

The EEM script in this section checks the interface counters, and if errors are seen, it generates an e-mail to the selected account.

For the script to operate properly, you need to define environment variables. The vari-ables include the following elements:

event manager environment _email_server e_mail_server.com event manager environment _email_to destination_account event manager environment _email_from source_account event manager environment _cron_entry 0-59/2 0-23/1 * * 0-7 event manager environment _show_cmd show interface include errors event manager directory user policy flash:

Note Variables that begin with an underscore (_) character are reserved for Cisco internal use and could be overwritten by system variables.

event manager policy interface_errors_email.tcl

Tip When configuring the source account using authentication to the SMTP server, use the following format:

event manager environment _email_server USERPASSWORD@SERVER_IP_ADDRESS

Step 1. The beginning of the Tcl script registers the CRON timer with user-defined parameters gleaned from the event manager variables:

::cisco::eem::event_register_timer cron name crontimer2 cron_entry

$_cron_entry maxrun_sec 240

Step 2. Verify the existence of all the environment variables you need for the script.

If any of them are not available, print out an error message and quit.

Step 3. Validate that the _email_server environment variable is set:

if {![info exists _email_server]} {

Chapter 4: Embedded Event Manager (EEM) 99

Step 4. If the environment variable _email_server has not been detected, save the error and quit:

set result \

“Policy cannot be run: variable _email_server has not been set”

error $result $errorInfo }

Step 5. The following section checks whether the required environment variable _email_from exists:

if {![info exists _email_from]} {

Step 6. If an error is detected in the environment variable (_email_from), save the reason for the error and exit the script:

set result \

“Policy cannot be run: variable _email_from has not been set”

error $result $errorInfo }

Step 7. The following section checks whether the required environment variable _email_to exists:

if {![info exists _email_to]} {

Step 8. If an error is detected in the environment variable (_email_to), save the reason for the error and exit the script:

set result \

“Policy cannot be run: variable _email_to has not been set”

error $result $errorInfo }

Step 9. The following section checks whether the _email_cc environment variable exists. Because this is not a required parameter, the variable will be config-ured as an empty string if nothing has been entered:

if {![info exists _email_cc]} {

Step 10. The _email_cc is an option, but must set to an empty string if not configured:

set _email_cc ““

}

Step 11. Verify that the _show_cmd environment variable is set, because this will be used to collect the IOS show command output and send it in the e-mail body:

if {![info exists _show_cmd]} {

Step 12. If there is an error, collect the information and exit the script:

set result \

“Policy cannot be run: variable _show_cmd has not been set”

error $result $errorInfo }

Step 13. Load the standard EEM libraries. The procedures error and cli_open are stan-dard EEM library procedures:

namespace import ::cisco::eem::*

namespace import ::cisco::lib::*

Step 14. Query the event info and log a message:

array set arr_einfo [event_reqinfo]

Step 15. If any problems were detected, variable _cerrno is set to a nonzero value, and the variable named _cerr contains the details of the problem:

if {$_cerrno != 0} {

set result [format “component=%s; subsys err=%s; posix err=%s;\n%s” \

$_cerr_sub_num $_cerr_sub_err $_cerr_posix_err $_cerr_str]

error $result }

Step 16. The following variables are used to store the time of the error:

global timer_type timer_time_sec set timer_type $arr_einfo(timer_type) set timer_time_sec $arr_einfo(timer_time_sec)

Step 17. Log a message:

set msg [format “timer event: timer type %s, time expired %s” \

$timer_type [clock format $timer_time_sec]]

Step 18. Send the message to the syslog process:

action_syslog priority info msg $msg

Step 19. If any problems were detected, the variable _cerrno is set to a nonzero value and the variable named _cerr will contain the details of the problem:

if {$_cerrno != 0} {

set result [format “component=%s; subsys err=%s; posix err=%s;\n%s” \

$_cerr_sub_num $_cerr_sub_err $_cerr_posix_err $_cerr_str]

error $result }

Step 20. Execute the show command from the environment variable _show_cmd:

if [catch {cli_open} result] {

Chapter 4: Embedded Event Manager (EEM) 101

Step 21. If there is a problem with the show command, end the script because of the error:

error $result $errorInfo } else {

Step 22. With a success, save the results to the array cli1:

array set cli1 $result }

Step 23. Because the cli_open was successful, use the variable fd from now on to access the CLI.

Step 24. Enter IOS enable mode for proper display of many show commands:

if [catch {cli_exec $cli1(fd) “en”} result] {

Step 25. In the event of an error, end the script:

error $result $errorInfo }

Step 26. Execute the IOS show command, and save the result:

if [catch {cli_exec $cli1(fd) $_show_cmd} result] {

Step 27. If a problem occurred executing the IOS show command, end the script now:

error $result $errorInfo } else {

Step 28. Save the output of the IOS show command in variable cmd_output:

set cmd_output $result }

Step 29. If a problem occurred closing access to the CLI, end the script now:

if [catch {cli_close $cli1(fd) $cli1(tty_id)} result] { error $result $errorInfo

}

Step 30. Log the success of the CLI command:

set msg [format “Command \”%s\” executed successfully” $_show_cmd]

Step 31. Send the message to the syslog process:

action_syslog priority info msg $msg

Step 32. If any problems were detected, the variable _cerrno is set to a nonzero value and the variable named _cerr will contain the details of the problem:

if {$_cerrno != 0} {

set result [format “component=%s; subsys err=%s; posix err=%s;\n%s” \

$_cerr_sub_num $_cerr_sub_err $_cerr_posix_err $_cerr_str]

error $result }

Collect the input and output errors using the IOS show command from the environment variable:

Step 1. Wherever a space appears, save it in the mylist variable:

set mylist [split $cmd_output “ “]

Step 2. Create an identical copy of the variable that will be modified as we work out the results:

set newlist [split $cmd_output “ “]

Step 3. Create counter variables to keep track of how many interface input and out-put errors were detected:

set inputerror 0 set outputerror 0

Step 4. The curpos variable is a pointer to a specific position in the string newlist.

Look for the first occurrence of the word input in mylist and save that loca-tion as curpos:

set curpos [lsearch $mylist input]

Step 5. Search through the string newlist until there are no longer any instances of the word input, at this time curpos will be set to 0:

while {$curpos > 0} {

Step 6. Set the variable prev to the location in the string just prior to the value of curpos:

set prev [expr $curpos - 1]

Step 7. The curerror variable contains the actual number of input errors:

set curerror [lindex $mylist $prev]

Step 8. Increment the variable inputerror if there were any input errors:

if {$curerror > 0} {incr inputerror}

Step 9. Change the word input to junk in the string newlist. This is done to prevent counting the same error multiple times:

set newlist [lreplace $newlist $curpos $curpos junk]

Step 10. Search for the word input in the string newlist:

set curpos [lsearch $newlist input]

}

Chapter 4: Embedded Event Manager (EEM) 103

Step 11. Look for the first occurrence of the word output in the string newlist and set the variable curpos to that location:

set curpos [lsearch $mylist output]

Step 12. Search through the string newlist until there are no longer any instances of the word output, at this time curpos will be set to 0:

while {$curpos > 0} {

Step 13. Set the variable prev to the location in the string just prior to the value of curpos:

set prev [expr $curpos - 1]

Step 14. The curerror variable contains the actual number of input errors:

set curerror [lindex $mylist $prev]

Step 15. Increment the variable inputerror if there were any input errors:

if {$curerror > 0} {incr outputerror}

Step 16. Change the word input to junk in the string newlist. This is done to prevent counting the same error multiple times:

set newlist [lreplace $newlist $curpos $curpos junk]

Step 17. Search for the word output in the string newlist:

set curpos [lsearch $newlist output]

}

Step 18. Check whether there were any interface errors:

if {$inputerror < 1 && $outputerror < 1} {

Step 19. If both variables inputerror and outputerror are 0, this indicates that there were not any errors:

set result “no interface errors found”

Step 20. Because there were not any errors detected, end the script:

error $result }

Send an e-mail indicating that the interface errors were detected.

Step 1. Collect the name of the Cisco IOS device:

set routername [info hostname]

if {[string match ““ $routername]} {

Step 2. If the IOS device is missing the hostname configuration command, display the following error message:

error “Host name is not configured”

}

Step 3. Concatenate the show command output with a standard e-mail template from the library and get the e-mail server IP address:

if [catch {smtp_subst [file join $tcl_library email_template_cmd.tm]}

result] {

error $result $errorInfo }

Step 4. Send the e-mail message:

if [catch {smtp_send_email $result} result] { error $result $errorInfo

}

Figure 4-6 shows the e-mail received from the IOS device.

In document Tcl Scripting for Cisco IOS (Page 115-121)