02-12-2014 11:30 AM
I am trying to write some Asynchronous TCL code to make things more efficent. This is just a simple example, but in reality it will SSH into a device, run a command, do some math, and write the output to the switch.
The whole "after" thing is throwing me off. When i run it locally trough tclsh86 , i need to run the "update" command to follow up with the results. How and what do i need to do to get this to work?
#***************************************CODE**********************************************************
::cisco::eem::event_register_timer watchdog time 15 maxrun 15
namespace import ::cisco::eem::*
namespace import ::cisco::lib::*
proc checkDevice { interface tempName aNumber waitTime} {
puts " "
puts "$tempName - Start"
after $waitTime
puts "$tempName - After"
if [catch {cli_write $interface "event manager environment tempName $aNumber"} _cli_result] {
error $_cli_result $errorInfo
}
puts "$tempName - EXIT"
}
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
}
after 0 checkDevice $cli1(fd) A 11 1000
after 0 checkDevice $cli1(fd) B 22 200
after 0 checkDevice $cli1(fd) C 33 4000
after 0 checkDevice $cli1(fd) D 44 1000
if [catch {cli_exec $cli1(fd) "exit"} _cli_result] {
error $_cli_result $errorInfo
}
catch {cli_close $cli1(fd) $cli1(tty_id)} result
02-13-2014 11:10 AM
Post your full script as an attachment (not pasted in line). You still have a typo somewhere.
02-13-2014 11:17 AM
I had to re-add the poll_timer thing otherwise it would error out right away saying that exiting is never set and would run indefinetly. In the prior config with the recursion instead of the while loop, it did not have that problem.
::cisco::eem::event_register_timer watchdog time 20 maxrun 20
namespace import ::cisco::eem::*
namespace import ::cisco::lib::*
set exiting 0
set poll_timer 10
set poll_q {}
proc checkDevice { interface tempName aNumber waitTime} {
puts "$tempName - Start"
after $waitTime procDevice $interface $tempName $aNumber $waitTime
}
proc procDevice { interface tempName aNumber waitTime } {
puts "$tempName"
while{1} {
global poll_q
puts "$tempName $tempName $tempName"
if [catch {cli_exec $interface "#ping 1.1.4.1 size 15000 repeat $waitTime"} _cli_result] {
error $_cli_result $errorInfo
}
}
puts "This shouldnt appear"
#after $waitTime procDevice $interface $tempName $aNumber $waitTime
}
proc check_q { } {
global poll_timer poll_q exiting
if { $poll_q != "" } {
puts "Q : $poll_q"
if { $poll_q == "DIE" } {
set exiting 1
}
set poll_q {}
}
after $poll_timer {::check_q}
}
puts "Start"
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) "config t"} _cli_result] {
# error $_cli_result $errorInfo
#}
puts "Before"
after 0 procDevice $cli1(fd) A 111 100
after 0 procDevice $cli1(fd) B 222 20
after 0 procDevice $cli1(fd) C 333 400
after 0 procDevice $cli1(fd) D 444 100
puts "After"
after $poll_timer {::check_q}
puts "After Timer"
vwait exiting
puts "After vwait"
if [catch {cli_exec $cli1(fd) "exit"} _cli_result] {
error $_cli_result $errorInfo
}
catch {cli_close $cli1(fd) $cli1(tty_id)} result
Message was edited by: Michael Moles - removed excess tab.
02-13-2014 11:21 AM
Can you attach this as a file using the advanced editor?
02-13-2014 11:23 AM
02-13-2014 11:28 AM
02-13-2014 11:29 AM
Note, because of the "while" loop, you will only see this run for A, but it should run.
02-13-2014 11:52 AM
Nope, its actually only going trough A. I set A and B to 1 PC, and C and D are on different PCs. It is interesting it doesnt error out and blow up at the end though. I guess the if you commented out was the culpret.
I cleared the counters on the switch and tested it out.
3560_Switch2#show int g 0/5 | inc packets [i|o]
1 packets input, 64 bytes, 0 no buffer
15 packets output, 1050 bytes, 0 underruns
3560_Switch2#show int G 0/6 | inc packets [i|o]
1 packets input, 64 bytes, 0 no buffer
15 packets output, 1050 bytes, 0 underruns
3560_Switch2#show int G 0/7 | inc packets [i|o]
5112 packets input, 6575736 bytes, 0 no buffer
4700 packets output, 6560534 bytes, 0 underruns
Mar 30 02:44:00.738: %HA_EM-6-LOG: SSHTest3.tcl: Start
Mar 30 02:44:01.084: %HA_EM-6-LOG: SSHTest3.tcl: Before
Mar 30 02:44:01.084: %HA_EM-6-LOG: SSHTest3.tcl: After
Mar 30 02:44:01.084: %HA_EM-6-LOG: SSHTest3.tcl: After Timer
Mar 30 02:44:01.084: %HA_EM-6-LOG: SSHTest3.tcl: A
Mar 30 02:44:01.084: %HA_EM-6-LOG: SSHTest3.tcl: A A A
Mar 30 02:44:03.999: %HA_EM-6-LOG: SSHTest3.tcl: A A A
Mar 30 02:44:06.788: %HA_EM-6-LOG: SSHTest3.tcl: A A A
Mar 30 02:44:09.824: %HA_EM-6-LOG: SSHTest3.tcl: A A A
Mar 30 02:44:13.106: %HA_EM-6-LOG: SSHTest3.tcl: A A A
Mar 30 02:44:17.924: %HA_EM-6-LOG: SSHTest3.tcl: A A A
Mar 30 02:44:19.581: %HA_EM-6-LOG: SSHTest3.tcl: After vwait
02-13-2014 11:58 AM
Yes. As I said in my follow-up reply, because you are using a while loop, only A will run. If you go back to using the after, you will get iterations for all of your instances.
02-13-2014 12:01 PM
02-13-2014 12:30 PM
I made a couple changes and put back in my ping because the delay is more inline on what im trying to do. When I run my status command on the device it will take a second or so. Use the after as the only delay could and does make it act differently.
Its failing hard again... i guess it wasnt the exit from before. Should i just remove the close considering this should never stop running?
Mar 30 03:15:58.232: %HA_EM-6-LOG: SSHTest4.tcl: Start
Mar 30 03:15:58.568: %HA_EM-6-LOG: SSHTest4.tcl: Before
Mar 30 03:15:58.568: %HA_EM-6-LOG: SSHTest4.tcl: After
Mar 30 03:15:58.568: %HA_EM-6-LOG: SSHTest4.tcl: After Timer
Mar 30 03:15:58.568: %HA_EM-6-LOG: SSHTest4.tcl: A A A
Mar 30 03:16:03.407: %HA_EM-6-LOG: SSHTest4.tcl: B B B
Mar 30 03:16:04.230: %HA_EM-6-LOG: SSHTest4.tcl: C C C
Mar 30 03:16:14.716: %HA_EM-6-LOG: SSHTest4.tcl: D D D
Mar 30 03:16:17.107: %HA_EM-6-LOG: SSHTest4.tcl: After vwait
Mar 30 03:16:17.107: %HA_EM-6-LOG: SSHTest4.tcl: Process Forced Exit- MAXRUN timer expired.
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: while executing
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: "catch {cli_close $cli1(fd) $cli1(tty_id)} result"
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: invoked from within
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: "$slave eval $Contents"
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: (procedure "eval_script" line 7)
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: invoked from within
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: "eval_script slave $scriptname"
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: invoked from within
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: "if {$security_level == 1} { #untrusted script
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: interp create -safe slave
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: interp share {} stdin slave
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: interp share {} stdout slave
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: ..."
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: (file "tmpsys:/lib/tcl/base.tcl" line 50)
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: Tcl policy execute failed:
Mar 30 03:16:17.112: %HA_EM-6-LOG: SSHTest4.tcl: Process Forced Exit- MAXRUN timer expired.
02-13-2014 12:48 PM
The constant reply seems to have chopped the text space a bunch by now... Here is a repost from above. (couldnt see a way to fix the one above)
Mar 30 03:16:18.360: %HA_EM-6-LOG: SSHTest4.tcl: Start
Mar 30 03:16:18.800: %HA_EM-6-LOG: SSHTest4.tcl: Before
Mar 30 03:16:18.800: %HA_EM-6-LOG: SSHTest4.tcl: After
Mar 30 03:16:18.800: %HA_EM-6-LOG: SSHTest4.tcl: After Timer
Mar 30 03:16:18.800: %HA_EM-6-LOG: SSHTest4.tcl: A A A
Mar 30 03:16:21.605: %HA_EM-6-LOG: SSHTest4.tcl: B B B
Mar 30 03:16:22.344: %HA_EM-6-LOG: SSHTest4.tcl: C C C
Mar 30 03:16:33.223: %HA_EM-6-LOG: SSHTest4.tcl: D D D
Mar 30 03:16:35.913: %HA_EM-6-LOG: SSHTest4.tcl: A A A
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: After vwait
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: Process Forced Exit- MAXRUN timer expired.
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: while executing
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: "catch {cli_close $cli1(fd) $cli1(tty_id)} result"
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: invoked from within
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: "$slave eval $Contents"
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: (procedure "eval_script" line 7)
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: invoked from within
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: "eval_script slave $scriptname"
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: invoked from within
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: "if {$security_level == 1} { #untrusted script
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: interp create -safe slave
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: interp share {} stdin slave
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: interp share {} stdout slave
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: ..."
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: (file "tmpsys:/lib/tcl/base.tcl" line 50)
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: Tcl policy execute failed:
Mar 30 03:16:37.197: %HA_EM-6-LOG: SSHTest4.tcl: Process Forced Exit- MAXRUN timer expired.
02-13-2014 12:52 PM
It appears to be working. The MAXRUN termination is expected since your maxrun is so low. The "close" is not the problem. The problem is you need to increase your maxrun to allow the policy to run longer. Increase it to 120, and you should see the policy live for two minutes before encountering the same forcible termination.
02-13-2014 12:58 PM
If you look at the timestamps you can see that they are running one after another and not parallel. A and B should be firing off multiple times before C completes. The message fires off before the ping command goes off, so D waited 15 seconds before even starting.
02-13-2014 01:04 PM
I'm not sure what script you're using now, but each invocation has different wait times (and thus different delays if you're using that ping). And remember, the next one doesn't start until the first one completes. You don't have different threads here. You're essentially scheduling four things to run asynchronously from the invocation, but in series. You're adding them to the wait loop, but that is still a single loop.
02-13-2014 01:30 PM
I was just about to give up... BUT i think i have an idea.
The reason why my code will run slow is that i am waiting for the output. So, what if i did cli_write instead of exec?
Each device will be on a seperate interface. So, if I do a write, i could just push the command to all of them at the same time. Then i could do a cli_read_pattern to read the data back. Is this possible, or does the read need to start before the output starts?
If not, do you think its even possible to acomplish this with a single tcl script?
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