112564a940661f08ca85c434b83faf43f7980d7d
[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 class EventListener:
61         def __init__(self,wake_up=None):
62                 self.handler = EventHandler()
63                 self.wake_up = wake_up
64                 self.deleters = {}
65                 self.load_deleter_modules()
66
67         def load_deleter_modules(self, deleter_dir=None):
68             if deleter_dir is None:
69                 if hasattr(Config(), "observer_deleters_dir"):
70                     deleter_dir = Config().observer_deleters_dir
71                 else:
72                     deleter_dir = "/opt/planetstack/observer/deleters"
73
74             for fn in os.listdir(deleter_dir):
75                 pathname = os.path.join(deleter_dir,fn)
76                 if os.path.isfile(pathname) and fn.endswith(".py") and (fn!="__init__.py"):
77                     module = imp.load_source(fn[:-3],pathname)
78                     for classname in dir(module):
79                         c = getattr(module, classname, None)
80
81                         # make sure 'c' is a descendent of Deleter and has a
82                         # provides field (this eliminates the abstract base classes
83                         # since they don't have a provides)
84
85                         if inspect.isclass(c) and issubclass(c, Deleter) and hasattr(c,"model") and c.model!=None:
86                             modelName = c.model
87                             if not modelName in self.deleters:
88                                 self.deleters[modelName] = []
89                             if not (c in self.deleters[modelName]):
90                                 self.deleters[modelName].append(c)
91             print 'loaded deleters: %s' % ",".join(self.deleters.keys())
92
93
94         def handle_event(self, payload):
95                 payload_dict = json.loads(payload)
96
97                 try:
98                         deletion = payload_dict.get('delete_flag', False)
99                         if (deletion):
100                                 model = payload_dict['model']
101                                 pk = payload_dict['pk']
102                                 model_dict = payload_dict['model_dict']
103
104                                 for deleter in self.deleters[model]:
105                                         try:
106                                             deleter()(pk, model_dict)
107                                         except:
108                                             # something is silently eating these
109                                             # exceptions...
110                                             traceback.print_exc()
111                                             raise
112
113                 except:
114                         deletion = False
115
116                 if (not deletion and self.wake_up):
117                         self.wake_up()
118
119         def random_client_id(self):
120                 try:
121                         return self.client_id
122                 except AttributeError:
123                         self.client_id = base64.urlsafe_b64encode(os.urandom(12))
124                         return self.client_id
125
126         def run(self):
127                 # This is our unique client id, to be used when firing and receiving events
128                 # It needs to be generated once and placed in the config file
129
130                 try:
131                         user = Config().feefie_client_user
132                 except:
133                         user = 'pl'
134
135                 try:
136                         clid = Config().feefie_client_id
137                 except:
138                         clid = self.random_client_id()
139
140                 f = Fofum(user=user)
141                 
142                 listener_thread = threading.Thread(target=f.listen_for_event,args=(clid,self.handle_event))
143                 listener_thread.start()