1d94f589e923582939033759b512c3a1e125ac0b
[plstackapi.git] / planetstack / observer / event_manager.py
1 import threading
2 import requests, json
3
4 from planetstack.config import Config
5 from observer.deleter import Deleter
6
7 import uuid
8 import os
9 import imp
10 import inspect
11 import base64
12 from fofum import Fofum
13 import json
14 import traceback
15
16 # decorator that marks dispatachable event methods        
17 def event(func):
18         setattr(func, 'event', func.__name__)
19         return func                     
20
21 class EventHandler:
22         # This code is currently not in use.
23         def __init__(self):
24                 pass 
25
26         @staticmethod
27         def get_events():
28                 events = []
29                 for name in dir(EventHandler):
30                         attribute = getattr(EventHandler, name)
31                         if hasattr(attribute, 'event'):
32                                 events.append(getattr(attribute, 'event'))
33                 return events
34
35         def dispatch(self, event, *args, **kwds):
36                 if hasattr(self, event):
37                         return getattr(self, event)(*args, **kwds)
38                         
39                 
40 class EventSender:
41         def __init__(self,user=None,clientid=None):
42                 try:
43                         user = Config().feefie_client_user
44                 except:
45                         user = 'pl'
46
47                 try:
48                         clid = Config().feefie_client_id
49                 except:
50                         clid = self.random_client_id()
51                         
52
53                 self.fofum = Fofum(user=user)
54                 self.fofum.make(clid)
55
56         def fire(self,**kwargs):
57                 kwargs["uuid"] = str(uuid.uuid1())
58                 self.fofum.fire(json.dumps(kwargs))
59
60         def random_client_id(self):
61                 try:
62                         return self.client_id
63                 except AttributeError:
64                         self.client_id = base64.urlsafe_b64encode(os.urandom(12))
65                         return self.client_id
66
67 class EventListener:
68         def __init__(self,wake_up=None):
69                 self.handler = EventHandler()
70                 self.wake_up = wake_up
71                 self.deleters = {}
72                 self.load_deleter_modules()
73
74         def load_deleter_modules(self, deleter_dir=None):
75             if deleter_dir is None:
76                 if hasattr(Config(), "observer_deleters_dir"):
77                     deleter_dir = Config().observer_deleters_dir
78                 else:
79                     deleter_dir = "/opt/planetstack/observer/deleters"
80
81             for fn in os.listdir(deleter_dir):
82                 pathname = os.path.join(deleter_dir,fn)
83                 if os.path.isfile(pathname) and fn.endswith(".py") and (fn!="__init__.py"):
84                     module = imp.load_source(fn[:-3],pathname)
85                     for classname in dir(module):
86                         c = getattr(module, classname, None)
87
88                         # make sure 'c' is a descendent of Deleter and has a
89                         # provides field (this eliminates the abstract base classes
90                         # since they don't have a provides)
91
92                         if inspect.isclass(c) and issubclass(c, Deleter) and hasattr(c,"model") and c.model!=None:
93                             modelName = c.model
94                             if not modelName in self.deleters:
95                                 self.deleters[modelName] = []
96                             if not (c in self.deleters[modelName]):
97                                 self.deleters[modelName].append(c)
98             print 'loaded deleters: %s' % ",".join(self.deleters.keys())
99
100
101         def handle_event(self, payload):
102                 payload_dict = json.loads(payload)
103
104                 try:
105                         deletion = payload_dict.get('delete_flag', False)
106                         if (deletion):
107                                 model = payload_dict['model']
108                                 pk = payload_dict['pk']
109                                 model_dict = payload_dict['model_dict']
110
111                                 for deleter in self.deleters[model]:
112                                         try:
113                                             deleter()(pk, model_dict)
114                                         except:
115                                             # something is silently eating these
116                                             # exceptions...
117                                             traceback.print_exc()
118                                             raise
119
120                 except:
121                         deletion = False
122
123                 if (not deletion and self.wake_up):
124                         self.wake_up()
125
126         def random_client_id(self):
127                 try:
128                         return self.client_id
129                 except AttributeError:
130                         self.client_id = base64.urlsafe_b64encode(os.urandom(12))
131                         return self.client_id
132
133         def run(self):
134                 # This is our unique client id, to be used when firing and receiving events
135                 # It needs to be generated once and placed in the config file
136
137                 try:
138                         user = Config().feefie_client_user
139                 except:
140                         user = 'pl'
141
142                 try:
143                         clid = Config().feefie_client_id
144                 except:
145                         clid = self.random_client_id()
146
147                 f = Fofum(user=user)
148                 
149                 listener_thread = threading.Thread(target=f.listen_for_event,args=(clid,self.handle_event))
150                 listener_thread.start()