[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