[asterisk-commits] jpeeler: branch jpeeler/event_watcher r241 - /asterisk/team/jpeeler/event_wat...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Apr 19 11:05:04 CDT 2010
Author: jpeeler
Date: Mon Apr 19 11:05:02 2010
New Revision: 241
URL: http://svnview.digium.com/svn/testsuite?view=rev&rev=241
Log:
commit working code, but still need to handle all the yaml/integration stuff
Added:
asterisk/team/jpeeler/event_watcher/tests/ami-monitor/
asterisk/team/jpeeler/event_watcher/tests/ami-monitor/client.py (with props)
asterisk/team/jpeeler/event_watcher/tests/ami-monitor/server.py (with props)
asterisk/team/jpeeler/event_watcher/tests/ami-monitor/starpy.conf (with props)
asterisk/team/jpeeler/event_watcher/tests/ami-monitor/test.py (with props)
Added: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/client.py
URL: http://svnview.digium.com/svn/testsuite/asterisk/team/jpeeler/event_watcher/tests/ami-monitor/client.py?view=auto&rev=241
==============================================================================
--- asterisk/team/jpeeler/event_watcher/tests/ami-monitor/client.py (added)
+++ asterisk/team/jpeeler/event_watcher/tests/ami-monitor/client.py Mon Apr 19 11:05:02 2010
@@ -1,0 +1,178 @@
+#! /usr/bin/env python
+
+from twisted.application import service, internet
+from twisted.internet import reactor
+from starpy import manager, fastagi, utilapplication, menu
+import os, logging, pprint, time, sys
+from basicproperty import common, propertied, basic
+import subprocess
+
+
+log = logging.getLogger('TestAMI')
+log.setLevel(logging.INFO)
+
+class EventWatcher(propertied.Propertied):
+
+ def __init__(self):
+ self.eventList = list()
+ self.count = 0
+ self.ordered = False
+
+ def set_ordered(self, ordered):
+ self.ordered = ordered
+
+ def add_event(self, event):
+ self.eventList.append(event)
+ self.count = self.count + 1
+
+ def set_events(self, ordered, list):
+ self.eventList = list
+ self.count = len(list)
+ self.ordered = ordered
+
+ def show_events(self):
+ print "Showing events"
+ for n in self.eventList:
+ print "Event: %s" % n
+
+ def get_events(self):
+ return self.eventList
+
+ def check_events(self):
+ for events in self.eventList:
+ matched = False
+ for event in events:
+ if "match" in event:
+ matched = True
+ continue
+ if not matched:
+ return False
+ return True
+
+ def timeout(self):
+ reactor.stop()
+
+ def dict_in_dict(self, d_set, d_subset):
+ #log.critical("JPEELER: Checking dictionaries")
+ return len(d_subset) == len(set(d_subset.items()) & set(d_set.items()))
+
+ def main( self ):
+ # Log into AMI
+ amiDF = APPLICATION.amiSpecifier.login().addCallbacks(self.onAMIConnect, self.onAMIFailure)
+
+ self.show_events()
+
+ def onAMIFailure(self, ami):
+ log.critical("Stop asterisk")
+
+ def onAMIConnect(self, ami):
+ """Register for AMI events"""
+ # XXX should handle asterisk reboots (at the moment the AMI
+ # interface will just stop generating events), not a practical
+ # problem at the moment, but should have a periodic check to be sure
+ # the interface is still up, and if not, should close and restart
+ log.debug('onAMIConnect')
+ ami.status().addCallback(self.onStatus, ami=ami)
+ print APPLICATION.amiSpecifier.getProperties()
+ print APPLICATION.amiSpecifier.username
+
+ if len(self.eventList) == 0:
+ log.critical("No events to monitor!")
+
+ ami.registerEvent(None, self.onAnyEvent)
+
+ def onAnyEvent(self, ami, event):
+
+ log.critical("DEBUG: RUNNING onAnyEvent")
+
+ if not self.ordered:
+ for next_events in self.eventList:
+ for next_event in next_events:
+ #log.critical("DEBUG: Looking at %s of type %s and count %s" % (next_events, type(next_events), len(next_events)))
+ if self.dict_in_dict(event, next_event):
+ next_event.update({"match": time.time()})
+ log.critical("new event %s" % next_event)
+ self.count = self.count - 1
+ if self.count == 0:
+ self.stopMonitoring(ami)
+ else:
+ index = abs(self.count - len(self.eventList))
+ for next_event in self.eventList[index]:
+ if self.dict_in_dict(event, next_event):
+ next_event.update({"match": time.time()})
+ log.critical("new event %s" % next_event)
+ self.count = self.count - 1
+ if self.count == 0:
+ self.stopMonitoring(ami)
+ continue
+
+ def stopMonitoring(self, ami):
+ ami.deregisterEvent(None, None)
+ if reactor.running:
+ reactor.stop()
+ log.critical("DONE")
+
+ def onStatus(self, events, ami=None):
+ log.debug("Initial channel status retrieved")
+ if events:
+ log.critical("Test expects no channels to have started yet, aborting!")
+ self.stopMonitoring(ami)
+ for event in events:
+ log.debug("Received event: %s", event)
+
+APPLICATION = utilapplication.UtilApplication()
+
+class EventSender:
+
+ def __init__(self):
+ self.test = 0
+
+
+def main():
+ logging.basicConfig()
+
+ log.setLevel(logging.DEBUG)
+ manager.log.setLevel(logging.DEBUG)
+
+ watcher = EventWatcher()
+
+ #scenario 1 with optional event matching
+ #event1 = [{'event' : 'Alarm', 'channel' : '18' }]
+ #event2 = [{'event' : 'Alarm', 'channel' : '17' }]
+ #event3 = [{'event' : 'Alarm', 'channel' : '20' }, {'event' : 'Alarm', 'channel' : '19'}]
+ #self.add_event(event1)
+ #self.add_event(event2)
+ #self.add_event(event3)
+ #self.set_ordered(False)
+
+ #scenario 2 with optional event matching
+ event1 = [{'event' : 'Alarm', 'channel' : '18' }]
+ event2 = [{'event' : 'Alarm', 'channel' : '17' }]
+ event3 = [{'event' : 'Alarm', 'channel' : '20' }, {'event' : 'Alarm', 'channel' : '19'}]
+ watcher.add_event(event1)
+ watcher.add_event(event2)
+ watcher.add_event(event3)
+ watcher.set_ordered(True)
+
+ # alternative event set up:
+ #self.set_events(False,
+ # [[{'event' : 'Alarm', 'channel' : '18' }],
+ # [{'event' : 'Alarm', 'channel' : '17' }],
+ # [{'event' : 'Alarm', 'channel' : '19' }, {'event' : 'Alarm', 'channel' : '20'}]])
+
+ reactor.callWhenRunning(watcher.main)
+ reactor.callLater(15, watcher.timeout)
+ reactor.run()
+
+ watcher.show_events()
+
+ if watcher.check_events():
+ print "DEBUG: all good!"
+ return 0
+ print "DEBUG: FAIL"
+ return 1
+
+if __name__ == "__main__":
+ sys.exit(main() or 0)
+
+# vim:sw=4:ts=4:expandtab:textwidth=79
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/client.py
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/client.py
------------------------------------------------------------------------------
svn:executable = *
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/client.py
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/client.py
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/server.py
URL: http://svnview.digium.com/svn/testsuite/asterisk/team/jpeeler/event_watcher/tests/ami-monitor/server.py?view=auto&rev=241
==============================================================================
--- asterisk/team/jpeeler/event_watcher/tests/ami-monitor/server.py (added)
+++ asterisk/team/jpeeler/event_watcher/tests/ami-monitor/server.py Mon Apr 19 11:05:02 2010
@@ -1,0 +1,161 @@
+#!/usr/bin/python
+from twisted.internet import reactor, protocol
+from twisted.internet.protocol import ServerFactory
+from twisted.protocols.basic import LineReceiver
+
+import sys
+
+class AMI(LineReceiver):
+ def __init__(self):
+ self.data_list = []
+ self.flag_logged_in = False
+ self.flag_async = False # TODO: make changeable, default False
+ self.send_delay = 2 # TODO: make changeable
+ self.events_list = []
+ self.events_iter = None
+
+ # made to match starpy naming
+ self.known_events = [
+ ['login', {'action':'login', 'username':'','secret':'', 'actionid':''}],
+ ['status', {'action':'status', 'actionid':''}],
+ ]
+
+ def set_events(self, events):
+ self.events_list = events
+
+ def compareKeys(self, received):
+ for f in self.known_events:
+ if f[1].keys() == received.keys():
+ print "DEBUG: matched event type: %s" % f[0]
+ del self.data_list[:]
+ return f[0]
+ return False
+ #if received.keys()
+ #print received
+
+ # old, used for event dict
+ #def send_event2(self, event):
+ # for k,v in event.iteritems():
+ # print "Firing %s: %s" % (k, v)
+ # sendline = k + ": " + v + "\r\n"
+ # self.transport.write(sendline)
+ # print ""
+ # self.transport.write("\r\n")
+ # self.prepare_events()
+
+ def send_event(self, event):
+ #print "DEBUG: event ", event
+ for line in event:
+ #print "DEBUG Firing ", line
+ newline = line + "\r\n"
+ self.transport.write(newline)
+ #print ""
+ self.transport.write("\r\n")
+ self.prepare_events()
+
+ def prepare_events(self):
+ #for event in self.factory.event_list:
+ if not self.events_iter:
+ self.events_iter = iter(self.factory.event_list)
+ try:
+ event = self.events_iter.next()
+ while event:
+ print "DEBUG: Looking at event: ", len(event), " ", event
+ if len(event) == 2: # we have a timeout to respect
+ reactor.callLater(event[1], self.send_event, event[0])
+ if not self.flag_async:
+ return
+ else:
+ self.send_event(event[0])
+ event = self.events_iter.next()
+ except StopIteration:
+ print "DEBUG!: done"
+
+ def authenticate(self, received):
+ if received['action'] != "login" or received['username'] != "jpeeler" or received['secret'] != "secret":
+ self.transport.write("Response: Error\r\nMessage: Authentication failed\r\n\r\n")
+ #self.transport.loseConnection()
+ else:
+ if received['actionid']:
+ self.transport.write("Response: Success\r\nActionID: " + received['actionid'] + "\r\nMessage: Authentication accepted\r\n\r\n")
+ else:
+ self.transport.write("Response: Success\r\nMessage: Authentication accepted\r\n\r\n")
+ self.flag_logged_in = True
+ reactor.callLater(self.send_delay, self.prepare_events)
+
+ def connectionMade(self):
+ self.transport.write("Asterisk Call Manager/1.1\r\n")
+ #self.setRawMode()
+ #DEBUG REMOVE THIS BELOW
+ print self.factory.event_list
+
+ def connectionLost(self, reason):
+ # TODO: == Connect attempt from '127.0.0.1' unable to authenticate
+ # or == Manager 'jpeeler' logged off from 127.0.0.1
+ print "bye"
+
+ def process_data(self):
+ # convert to dictionary
+ d = dict([x.split(':') for x in self.data_list])
+ # more forgiving than the real thing
+ for k,v in d.iteritems():
+ d[k] = v.strip()
+ validinput = self.compareKeys(d)
+ if not validinput:
+ if self.flag_logged_in:
+ self.transport.write("Response: Error\r\nMessage: Invalid/unknown command: %s\r\n\r\n" % d)
+ else:
+ self.transport.write("Response: Error\r\nMessage: Permission denied\r\n\r\n")
+ del self.data_list[:]
+ elif not self.flag_logged_in:
+ self.authenticate(d)
+ else:
+ print "Valid action detected", d['action']
+ if d['action'] == "Status" and d['actionid']: #TODO: make case insensitive
+ print "DEBUG: status good"
+ self.transport.write("Response: Success\r\nActionID: " + d['actionid'] + "\r\nMessage: Channel status will follow\r\n\r\n")
+ self.transport.write("Event: StatusComplete\r\nActionID: " + d['actionid'] + "\r\nItems: 0\r\n\r\n")
+ print "Response: Success\r\nActionID: " + d['actionid'] + "\r\nMessage: Channel status will follow\r\n\r\n"
+ print "Event: StatusComplete\r\nActionID: " + d['actionid'] + "\r\nItems: 0\r\n\r\n"
+
+ def lineReceived(self, data):
+ if data == '':
+ self.process_data()
+ elif ":" in data:
+ self.data_list.append(data)
+ else:
+ print "Yikes, this is not a real AMI server. Bad input received!"
+ #print "DEBUG: line", data
+
+class MyFactory(ServerFactory):
+ protocol = AMI
+
+ def __init__(self, events):
+ self.event_list = events
+
+def main():
+ #events = ([[['Event':'Alarm', 'Privilege':'system,all', 'Alarm':'Recovering', 'Channel':'17'], 3],
+ #[['Event':'Alarm', 'Privilege':'system,all', 'Alarm':'Recovering', 'Channel':'18']],
+ #[['Event':'Alarm', 'Privilege':'system,all', 'Alarm':'Recovering', 'Channel':'19'], 3]])
+
+ #scenario1
+ #events = ([[['Event: Alarm', 'Privilege: system,all', 'Alarm: Recovering', 'Channel: 17']],
+ #[['Event: Alarm', 'Privilege: system,all', 'Alarm: Recovering', 'Channel: 18']],
+ #[['Event: Alarm', 'Privilege: system,all', 'Alarm: Recovering', 'Channel: 19']]])
+
+ #scenario2
+ events = ([[['Event: Alarm', 'Privilege: system,all', 'Alarm: Recovering', 'Channel: 17']],
+ [['Event: Alarm', 'Privilege: system,all', 'Alarm: Recovering', 'Channel: 18']],
+ [['Event: Alarm', 'Privilege: system,all', 'Alarm: Recovering', 'Channel: 19']],
+ [['Event: Alarm', 'Privilege: system,all', 'Alarm: Recovering', 'Channel: 17']],
+ [['Event: Alarm', 'Privilege: system,all', 'Alarm: Recovering', 'Channel: 18']],
+ [['Event: Alarm', 'Privilege: system,all', 'Alarm: Recovering', 'Channel: 19']]])
+
+ #factory = protocol.ServerFactory()
+ #factory.protocol = AMI
+ factory = MyFactory(events)
+ reactor.listenTCP(5038, factory)
+ reactor.run()
+
+if __name__ == '__main__':
+ sys.exit(main() or 0)
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/server.py
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/server.py
------------------------------------------------------------------------------
svn:executable = *
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/server.py
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/server.py
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/starpy.conf
URL: http://svnview.digium.com/svn/testsuite/asterisk/team/jpeeler/event_watcher/tests/ami-monitor/starpy.conf?view=auto&rev=241
==============================================================================
--- asterisk/team/jpeeler/event_watcher/tests/ami-monitor/starpy.conf (added)
+++ asterisk/team/jpeeler/event_watcher/tests/ami-monitor/starpy.conf Mon Apr 19 11:05:02 2010
@@ -1,0 +1,6 @@
+[AMI]
+username=jpeeler
+secret=secret
+#server=jbp2.digium.internal
+server=localhost
+port=5038
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/starpy.conf
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/starpy.conf
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/starpy.conf
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/test.py
URL: http://svnview.digium.com/svn/testsuite/asterisk/team/jpeeler/event_watcher/tests/ami-monitor/test.py?view=auto&rev=241
==============================================================================
--- asterisk/team/jpeeler/event_watcher/tests/ami-monitor/test.py (added)
+++ asterisk/team/jpeeler/event_watcher/tests/ami-monitor/test.py Mon Apr 19 11:05:02 2010
@@ -1,0 +1,42 @@
+#! /usr/bin/env python
+
+#import jeff
+from jeff import *
+import sys
+
+from twisted.application import service, internet
+from twisted.internet import reactor
+from starpy import manager, fastagi, utilapplication, menu
+import os, logging, pprint, time, sys
+from basicproperty import common, propertied, basic
+import subprocess
+
+
+def main():
+ watcher = EventWatcher()
+
+ #scenario 2 with optional event matching
+ event1 = [{'event' : 'Alarm', 'channel' : '18' }]
+ event2 = [{'event' : 'Alarm', 'channel' : '17' }]
+ event3 = [{'event' : 'Alarm', 'channel' : '20' }, {'event' : 'Alarm', 'channel' : '19'}]
+ watcher.add_event(event1)
+ watcher.add_event(event2)
+ watcher.add_event(event3)
+ watcher.set_ordered(True)
+
+ reactor.callWhenRunning(watcher.main)
+ reactor.callLater(15, watcher.timeout)
+ reactor.run()
+
+ watcher.show_events()
+
+ if watcher.check_events():
+ print "DEBUG: all good!"
+ return 0
+ print "DEBUG: FAIL"
+ return 1
+
+if __name__ == "__main__":
+ sys.exit(main() or 0)
+
+# vim:sw=4:ts=4:expandtab:textwidth=79
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/test.py
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/test.py
------------------------------------------------------------------------------
svn:executable = *
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/test.py
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: asterisk/team/jpeeler/event_watcher/tests/ami-monitor/test.py
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the asterisk-commits
mailing list