12-20-2010 08:28 AM
Hi all,
I've been playing around with some basic scripts with EEM and TCL to build a little script for letting us know via email when a UK Premium number is called. I got the following working:
MIKE-TEST-VGW(config)#
event manager environment _email_server 10.1.2.2
event manager environment _email_to test@acme.co.uk
event manager environment _email_from test2@acme.co.uk
event manager applet PREMIUMNUMBERCALLED
event syslog pattern "is now connected to 09"
action 1.0 info type routername
action 1.05 cli command "enable"
action 1.1 cli command "del /force flash:isdn_active"
action 1.2 cli command "show clock | append flash:isdn_active"
action 1.3 cli command "show isdn active | append flash:isdn_active"
action 1.4 cli command "more flash:isdn_active"
action 1.5 syslog msg "Sending email to ServiceDesk"
action 1.6 mail server "$_email_server" to "$_email_to" from "$_email_from" subject "Premium rate call detected on VGW $_info_routername" body "$_cli_result"
action 1.7 syslog msg "Email sent"
So the next step was to do something more clever. I wanted to introduce if statements to tell if the number dialled is either an international call, or Premium. If it's a premium call then alert straight away. If it's an international call, then check after an hour to see if the call is still up and then alert (In that it's possibly a dodgy call and you should investigate).
I fudged an example TCL script but it fails at the first line. If I type in tclsh and try to paste in the following, it errors:
MIKE-VGW-TEST(tcl)#::cisco::eem::event_register_syslog pattern "ISDN"
invalid command name "::cisco::eem::event_register_syslog" ^
% Invalid input detected at '^' marker.
The test router I'm using is a 3845, running SP Services 12.4(24)T3. This is running EEM 3.0.
Any ideas what might be causing this?
Any help appreciated!
Thanks,
Mike.
12-20-2010 11:27 AM
EEM Tcl policy is not the same as tclsh script though. Check out the following thread on how to register an EEM Tcl policy:
12-20-2010 11:57 AM
As Yi Jia points out, tclsh is not the same as EEM. You will not be able to use those EEM procedures in tclsh. However, given your code, you don't need to use Tcl at all. It sounds like programmatic applet syntax will suffice. If you post the specifics of your conditional, I can give you an example.
12-22-2010 03:46 AM
Hey guys, thanks for your offers of help!
I've got the TCL scripting book that you were part of Joe and it's become my bible for the next few weeks! As always with learning a new language though, it's the syntax that's letting me down (I think).
Apologies for the delay in responding though.
So the reason why I want to do this in TCL rather than Event Manager is that I'm trying to use this as a bit of a platform for building more structured code. So please forgive me if I ask that we don't do this using EEM (Unless if we can't do it in TCL).
A couple of basic questions first:
1) If TCLSH is not the same as TCL, I guess the question is why does it exist?
I tried to run that command in TCLSH because I actually have a script in a .tcl file saved in flash, and had the same error when attempting to run the script. Therefore question 2:
2) Just for the sake of my potential stupidity, how do you run a script(.tcl file) that is sitting in flash?
Finally, the butchered script is as follows (With some pseudocode shoved in for good measure):
#------------------------------------------------------------------
# EEM policy that will monitor SYSLOG for 0900 number successful calls.
# If a successful syslog message is detected then,
# send an email alert to ServiceDesk with the time and current
# "show isdn active" information.
#
#------------------------------------------------------------------
### The following EEM environment variables are used:
###
### _email_server
### - A Simple Mail Transfer Protocol (SMTP)
### mail server used to send e-mail.
### Example: _email_server mailserver.example.com
# NAMESPACE IMPORT
# Imports Cisco specific TCL extensions that can be used in the body of the code such as the first line of the code above.
# Add the following lines to your script:
# Register for a Syslog event. Event Detector: Syslog
# Match pattern for ISDN Connect Messages
::cisco::eem::event_register_Syslog pattern "%ISDN-6-CONNECT"
namespace import ::cisco::eem::*
namespace import ::cisco::lib::*
# Set array for event_reqinfo
# Array is populated with additional event information
array set Syslog_info [event_reqinfo]
set msg $Syslog_info(msg)
# Set routername variable for use later
set routername [info hostname]
# Debug message to verify a premium number is now a connected call
# action_Syslog msg "Premium Number Detected"
# Open CLI to get show isdn status
#
# ------------------- cli open -------------------
#
if [catch {cli_open} result] {
error $result $errorInfo
} else {
array set cli $result
}
if [catch {cli_exec $cli(fd) "enable"} result] {
error $result $errorInfo
}
# Execute CLI command and store in variable
if [catch {cli_exec $cli(fd) "show isdn active"} isdnactive ] {
error $result $errorInfo
}
#
#--------------------- cli close ------------------------
#
cli_close $cli(fd) $cli(tty_id)
# ACTION if call is a premium call
if [regexp {is connected to 09} $msg] {
action_Syslog msg "Premium call detected"
# save exact execution time
set time_now [clock seconds]
set time_now [clock format $time_now -format "%T %Z %a %b %d %Y"]
# EMAIL MESSAGE
# This manually creates a text message with specific format to be used by the
# smtp_send_email command later to send an email alert.
#
# Ensure the following are configured:
# ip domain-name
#
# If a hostname is used for mailservername, ensure the following are configured:
# ip name-server
# ip domain-lookup
#
# NOTE: Change environment variable _email_server to your SMTP server
#
# The email below references the following variables:
#
# $routername: hostname of device
# $time_now: time when specific Syslog message was detected
# $msg: Syslog message received
# $isdnactive: output of "show isdn active"
#
#
set email_message "Mailservername: $_email_server
From: mgerrard@acme.co.uk
To: servicedesk@acme.co.uk
Cc:
Subject: EEM: Premium Phone Call Detected On $routername
This email is generated by EEM.
$time_now
$msg
show ISDN active:
$isdnactive
"
# Send email message
if {[catch {smtp_send_email $email_message} result]} {
set result "Email send failed"
} else {
set result "Email Sent To ServiceDesk"
}
# Debug message to check email transmission status
action_Syslog msg "$result"
#Close ACTION
}
#ACTION if call is international
if [regexp {is connected to 00} $msg] {
action_Syslog msg "International call detected"
# save exact execution time
set time_now [clock seconds]
set time_now [clock format $time_now -format "%T %Z %a %b %d %Y"]
PSEUDOCODE:
Kick off a cron timer event that checks ISDN active table every 10 minutes.
set still active = true
If call is no longer active, then end script
If call has been up longer than 1 hour, then send the email with isdn active included
#EMAIL MESSAGE
set email_message "Mailservername: $_email_server
From: mgerrard@acme.co.uk
To: servicedesk@acme.com
Cc:
Subject: EEM: Suspicious International call on $routername
This email is generated by EEM.
$time_now
$msg
show isdn active:
$isdnactive
"
# Send email message
if {[catch {smtp_send_email $email_message} result]} {
set result "Email send failed"
} else {
set result "Email Sent"
}
Debug message to check email transmission status
action_Syslog msg "$result"
Close ACTION
}
12-22-2010 04:15 AM
Ignore Question 2, yidabear already provided the access in the other thread!
Ta.
Mike.
12-22-2010 02:10 PM
I think you're confusing EEM and Tcl. EEM and Tcl are not mutually exclusive. EEM can use Tcl. However, it uses its own Tcl interpreter. It's the same Tcl 8.3.4 that tclsh uses, but it provides more (or different) libraries and capabilities. Both tclsh and EEM Tcl are Tcl.
The subsystem you use depends on what you want to do. In this case, it looks like you're trying to run something that is event-driven. In that case you must use EEM. With EEM you can use either applet policies or Tcl policies. Since you'd like to write some structured code around your event, Tcl is the way to go. Your initial applet policy can be easily converted to Tcl, then extended to meet your needs. Here is the Tcl version.
::cisco::eem::event_register_syslog pattern "is now connected to 09"
namespace import ::cisco::eem::*
namespace import ::cisco::lib::*
array set _sinfo [sys_reqinfo_routername]
set _info_routername $_sinfo(routername)
if [catch {cli_open} result] {
error $result $errorInfo
} else {
array set cli1 $result
}
if [catch {cli_exec $cli1(fd) "enable"} _cli_result] {
error $_cli_result $errorInfo
}
if [catch {cli_exec $cli1(fd) "del /force flash:isdn_active"} _cli_result] {
error $_cli_result $errorInfo
}
if [catch {cli_exec $cli1(fd) "show clock | append flash:isdn_active"} _cli_result] {
error $_cli_result $errorInfo
}
if [catch {cli_exec $cli1(fd) "show isdn active | append flash:isdn_active"} _cli_result] {
error $_cli_result $errorInfo
}
if [catch {cli_exec $cli1(fd) "more flash:isdn_active"} _cli_result] {
error $_cli_result $errorInfo
}
action_syslog msg "Sending email to ServiceDesk"
set mail_pre "Mailservername: $_email_server\n"
append mail_pre "From: $_email_from\n"
append mail_pre "To: $_email_to\n"
append mail_pre "Cc: \n"
append mail_pre "Subject: Premium rate call detected on VGW $_info_routername\n\n"
append mail_pre "$_cli_result\n\n"
set mail_msg [uplevel #0 [list subst -nobackslashes -nocommands $mail_pre]]
if [catch {smtp_send_email $mail_msg} result] {
error $result $errorInfo
}
action_syslog msg "Email sent"
# Close open cli before exit.
if [catch {cli_close $cli1(fd) $cli1(tty_id)} result] {
error $result $errorInfo
}
Hopefully, this will give you a functional starting point to help you crank out the policy you want.
12-22-2010 02:22 PM
For the scheduling piece, you will want to create a new timer policy to check to see if the call is still active. Cron might be a bit of an of an overkill here. You could use watchdog instead. From your main policy, open a file in your EEM policy directory, and dump the contents. I'm not sure exactly what to look for in the "show isdn active" output to give a concrete example, but essentially, you'd write something like the following out to your timer policy (called watch_call_timer_pol.tcl).
::cisco::eem::event_register_timer watchdog time 600 name "watch_call_timer"
namespace import ::cisco::eem::*
namespace import ::cisco::lib::*
if { [catch {cli_open} result] } {
error $result $errorInfo
}
array set cli $result
cli_exec $cli(fd) "enable"
set output [cli_exec $cli(fd) "show isdn active"]
set active_time -1
# Look to see how long call has been active...
# Note: we may need a call ID that was set from the previous, main
# policy. If so, we can save the ID in a context and retrieve it
# here.
if { $active_time == -1 } {
# Call is dead, so we can stop looking.
cli_exec $cli(fd) "config t"
cli_exec $cli(fd) "no event manager policy watch_call_timer_pol.tcl"
cli_exec $cli(fd) "end"
} elseif { $active_time >= 3600 } {
# Call has been active for an hour or more, so send email...
}
catch {cli_close $cli(fd) $cli(tty_id)}
12-23-2010 03:51 AM
Most excellent Joe, thanks very much for the pointers. I'll give this a go in the new year and see if it all works. The reason for doing this is more to get my head round the syntax of building TCL rather than trying to satisfy a particular need or problem. It all looks rather fun!
I suspect to solve the issue of the call ID, I can either search for a call ID in the ISDN active table (If there is one); or I dump out the isdn active table and use a "first" command to hunt for the strings and try to manipulate them in some way. The good thing is though, providing your script provided works ok, is that I can learn a thing or two out of all of this.
Again many thanks, and merry xmas!
Mike.
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide