From: Jeff L. <je...@je...> - 2016-03-22 18:14:39
|
Hello, I started what I hoped to be a simple hack this morning and found pyst. I would like to use the asterisk AMI to pull a list of SIP peers and their status. I am doing this today on a number of our customer asterisk instances using bourne shell and "asterisk -x "sip show peers'", then parsing the output, but this is turning out to be quite an intensive act to perform on the instance, thus the desire to use AMI. After a few hours of surfing and playing around, I have ended up with this: -------------- root@jlpenha:/usr/local/bin# more pypeers #!/usr/bin/python from asterisk import manager import signal ip = "127.0.0.1" user = "XXX" passwd = "XXX" peers = [] def handleEvent(event, ami): print ("Received event: %s" % event.name) if event.name == 'PeerlistComplete': printResults() ami.close() #print ("Received event Header: %s" % event.headers) #add to peers[] def eventTimeout(signum, frame): print "Timeout!" ami.close() def printResults(): print peers ami = manager.Manager() ami.connect(ip) ami.login(user, passwd) ami.register_event('PeerEntry', handleEvent) ami.register_event('PeerlistComplete', handleEvent) signal.signal(signal.SIGALRM, eventTimeout) # Sippeers tends to hang? signal.alarm(5) response = ami.send_action({'Action' : 'Sippeers'}) ami.message_loop() print response --------------- In testing I first noticed that about 30% of the time the script hangs, thus I implemented the signal timeout. It seems to hang because I never get the PeerlistComplete event. Is this a problem with asterisk not sending it or some kind of bug in pyst? I next noticed that I rarely get the same number of peers: -------- root@jlpenha:/usr/local/bin# ./pypeers | wc -l 27 root@jlpenha:/usr/local/bin# ./pypeers | wc -l 68 root@jlpenha:/usr/local/bin# ./pypeers | wc -l 71 root@jlpenha:/usr/local/bin# ./pypeers | wc -l 67 root@jlpenha:/usr/local/bin# ./pypeers | wc -l 64 ------- This can't possibly be so difficult. Surely someone has done what I am trying to do, though I haven't found any examples with lots of googling today. Can anyone chime in? Thanks! j |
From: Ralf S. <rs...@ru...> - 2016-03-23 16:15:03
|
On Tue, Mar 22, 2016 at 12:54:44PM -0500, Jeff LaCoursiere wrote: > > In testing I first noticed that about 30% of the time the script hangs, > thus I implemented the signal timeout. It seems to hang because I never > get the PeerlistComplete event. Is this a problem with asterisk not > sending it or some kind of bug in pyst? > > I next noticed that I rarely get the same number of peers: > > -------- > > root@jlpenha:/usr/local/bin# ./pypeers | wc -l > 27 > root@jlpenha:/usr/local/bin# ./pypeers | wc -l > 68 > root@jlpenha:/usr/local/bin# ./pypeers | wc -l > 71 > root@jlpenha:/usr/local/bin# ./pypeers | wc -l > 67 > root@jlpenha:/usr/local/bin# ./pypeers | wc -l > 64 You can debug this by looking with wireshark (or tcpdump) to the traffic on port 5038. This should show you in what sequence you receive which messages from asterisk. Looking at your code: You should *not* call ami.message_loop explicitly in your code. This is done behind the scenes by the ami implementation of pyst. So you're probably creating a race condition there between your call to ami.message_loop and the one that is called by a thread created in the __init__ method of the Manager object. So you really should leave all the processing to the thread created by Manager and do something else (sleep?) in the main program. Ralf -- Dr. Ralf Schlatterbeck Tel: +43/2243/26465-16 Open Source Consulting www: http://www.runtux.com Reichergasse 131, A-3411 Weidling email: of...@ru... |
From: Jeff L. <je...@je...> - 2016-03-24 17:44:42
|
On 03/23/2016 10:59 AM, Ralf Schlatterbeck wrote: > On Tue, Mar 22, 2016 at 12:54:44PM -0500, Jeff LaCoursiere wrote: >> In testing I first noticed that about 30% of the time the script hangs, >> thus I implemented the signal timeout. It seems to hang because I never >> get the PeerlistComplete event. Is this a problem with asterisk not >> sending it or some kind of bug in pyst? >> >> I next noticed that I rarely get the same number of peers: >> >> -------- >> >> root@jlpenha:/usr/local/bin# ./pypeers | wc -l >> 27 >> root@jlpenha:/usr/local/bin# ./pypeers | wc -l >> 68 >> root@jlpenha:/usr/local/bin# ./pypeers | wc -l >> 71 >> root@jlpenha:/usr/local/bin# ./pypeers | wc -l >> 67 >> root@jlpenha:/usr/local/bin# ./pypeers | wc -l >> 64 > You can debug this by looking with wireshark (or tcpdump) to the traffic > on port 5038. This should show you in what sequence you receive which > messages from asterisk. > > Looking at your code: You should *not* call ami.message_loop explicitly > in your code. This is done behind the scenes by the ami implementation > of pyst. So you're probably creating a race condition there between your > call to ami.message_loop and the one that is called by a thread created > in the __init__ method of the Manager object. > > So you really should leave all the processing to the thread created by > Manager and do something else (sleep?) in the main program. > > Ralf Hi, yes indeed that was the main issue. I guess two threads were fighting for the responses. Getting rid of that call and just looping forever around a sleep makes it always get all of the peers. However now I can't seem to get the main loop to exit - the timeout alarm does it eventually (after five seconds), but the same code in the handler doesn't. You can see that "printResult()" runs (the empty array shows in stdout), but the sys.exit(0) doesn't exit the parent thread I guess? I get the impression that this library is really designed around making a multi-threaded daemon that just lives to process AMI events. What I am looking for hardly requires that - a single threaded utility that just grabs some info and exits seems to be difficult to code :) Can anyone supply an example that does something similar? Here is what I have now: #!/usr/bin/python from asterisk import manager import signal import time import sys ip = "127.0.0.1" user = "XXX" passwd = "XXX" peers = [] def handleEvent(event, ami): print ("Received event: %s" % event.name) if event.name == 'PeerlistComplete': printResults() ami.close() sys.exit(0) #print ("Received event Header: %s" % event.headers) def eventTimeout(signum, frame): print "Timeout!" ami.close() sys.exit(1) def printResults(): print peers ami = manager.Manager() ami.connect(ip) ami.login(user, passwd) ami.register_event('PeerEntry', handleEvent) ami.register_event('PeerlistComplete', handleEvent) signal.signal(signal.SIGALRM, eventTimeout) # Sippeers tends to hang? signal.alarm(5) response = ami.send_action({'Action' : 'Sippeers'}) #ami.message_loop() while(1): time.sleep(10) ----- and the result: root@jlpenha:/usr/local/bin# ./pypeers Received event: PeerEntry Received event: PeerEntry Received event: PeerEntry [snip] Received event: PeerEntry Received event: PeerlistComplete [] Timeout! The "Timeout!" doesn't appear for five seconds... Cheers, j |
From: Ralf S. <rs...@ru...> - 2016-03-31 12:07:39
|
On Thu, Mar 24, 2016 at 12:44:33PM -0500, Jeff LaCoursiere wrote: > if event.name == 'PeerlistComplete': > printResults() > ami.close() > sys.exit(0) This will exit the thread created by manager, not your main thread. You generally shouldn't call exit in the callback functions, these are called by the manager thread. I'd set up a Queue between your callbacks and the main loop and wait for an event on the queue in the main loop (where you're currently only sleeping). Then when receiving that event you can safely exit the main loop. I'm not sure calling ami.close in the callback is a good idea either, you'd probably do that in the main loop, too, e.g. (code completely untested) from Queue import Queue queue = Queue () ... ami = manager.Manager() ... def handleEvent(event, ami): print ("Received event: %s" % event.name) if event.name == 'PeerlistComplete': ... queue.put("End") ... item = queue.get () ami.close () sys.exit (0) Ralf -- Dr. Ralf Schlatterbeck Tel: +43/2243/26465-16 Open Source Consulting www: http://www.runtux.com Reichergasse 131, A-3411 Weidling email: of...@ru... |