blob: 112564a940661f08ca85c434b83faf43f7980d7d [file] [log] [blame]
Tony Mack79a49c82013-06-15 23:51:57 -04001import threading
2import requests, json
Sapan Bhatia66f4e612013-07-02 12:12:38 -04003
Sapan Bhatia66f4e612013-07-02 12:12:38 -04004from planetstack.config import Config
Scott Baker6ecd4262014-01-21 23:15:21 -08005from observer.deleter import Deleter
Tony Mack79a49c82013-06-15 23:51:57 -04006
Scott Bakerc1c45f82014-01-21 16:23:51 -08007import uuid
Sapan Bhatia9182b322013-06-25 16:22:14 -04008import os
Scott Baker6ecd4262014-01-21 23:15:21 -08009import imp
10import inspect
Sapan Bhatia9182b322013-06-25 16:22:14 -040011import base64
Tony Mack5c0c4552013-07-03 09:36:51 -040012from fofum import Fofum
Sapan Bhatiadbaf1932013-09-03 11:28:52 -040013import json
Scott Baker6ecd4262014-01-21 23:15:21 -080014import traceback
Sapan Bhatia9182b322013-06-25 16:22:14 -040015
Sapan Bhatia9faf7b02013-10-09 10:27:14 -040016# decorator that marks dispatachable event methods
Tony Mack79a49c82013-06-15 23:51:57 -040017def event(func):
Sapan Bhatia9faf7b02013-10-09 10:27:14 -040018 setattr(func, 'event', func.__name__)
19 return func
Tony Mack79a49c82013-06-15 23:51:57 -040020
21class EventHandler:
Sapan Bhatia9faf7b02013-10-09 10:27:14 -040022 # This code is currently not in use.
23 def __init__(self):
24 pass
Tony Mack79a49c82013-06-15 23:51:57 -040025
Sapan Bhatia9faf7b02013-10-09 10:27:14 -040026 @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
Tony Mack79a49c82013-06-15 23:51:57 -040034
Sapan Bhatia9faf7b02013-10-09 10:27:14 -040035 def dispatch(self, event, *args, **kwds):
36 if hasattr(self, event):
37 return getattr(self, event)(*args, **kwds)
38
39
Sapan Bhatia66f4e612013-07-02 12:12:38 -040040class EventSender:
Sapan Bhatia9faf7b02013-10-09 10:27:14 -040041 def __init__(self,user=None,clientid=None):
42 try:
43 user = Config().feefie_client_user
44 except:
45 user = 'pl'
Sapan Bhatia66f4e612013-07-02 12:12:38 -040046
Sapan Bhatia9faf7b02013-10-09 10:27:14 -040047 try:
48 clid = Config().feefie_client_id
49 except:
50 clid = self.random_client_id()
51
Sapan Bhatia66f4e612013-07-02 12:12:38 -040052
Sapan Bhatia9faf7b02013-10-09 10:27:14 -040053 self.fofum = Fofum(user=user)
54 self.fofum.make(clid)
55
Scott Bakerc1c45f82014-01-21 16:23:51 -080056 def fire(self,**kwargs):
57 kwargs["uuid"] = str(uuid.uuid1())
Scott Bakerc1c45f82014-01-21 16:23:51 -080058 self.fofum.fire(json.dumps(kwargs))
Tony Mack79a49c82013-06-15 23:51:57 -040059
60class EventListener:
Sapan Bhatia9faf7b02013-10-09 10:27:14 -040061 def __init__(self,wake_up=None):
62 self.handler = EventHandler()
63 self.wake_up = wake_up
Scott Baker6ecd4262014-01-21 23:15:21 -080064 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
Tony Mack79a49c82013-06-15 23:51:57 -040093
Sapan Bhatia9faf7b02013-10-09 10:27:14 -040094 def handle_event(self, payload):
95 payload_dict = json.loads(payload)
Sapan Bhatia43c3a772013-07-03 11:19:07 -040096
Sapan Bhatia9faf7b02013-10-09 10:27:14 -040097 try:
Scott Bakerc1c45f82014-01-21 16:23:51 -080098 deletion = payload_dict.get('delete_flag', False)
Sapan Bhatia9faf7b02013-10-09 10:27:14 -040099 if (deletion):
100 model = payload_dict['model']
101 pk = payload_dict['pk']
Scott Baker6ecd4262014-01-21 23:15:21 -0800102 model_dict = payload_dict['model_dict']
Sapan Bhatiadbaf1932013-09-03 11:28:52 -0400103
Scott Baker6ecd4262014-01-21 23:15:21 -0800104 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
Scott Bakerc1c45f82014-01-21 16:23:51 -0800112
Sapan Bhatia9faf7b02013-10-09 10:27:14 -0400113 except:
114 deletion = False
Sapan Bhatia66f4e612013-07-02 12:12:38 -0400115
Sapan Bhatia9faf7b02013-10-09 10:27:14 -0400116 if (not deletion and self.wake_up):
117 self.wake_up()
Scott Bakerc1c45f82014-01-21 16:23:51 -0800118
Sapan Bhatia9faf7b02013-10-09 10:27:14 -0400119 def random_client_id(self):
Sapan Bhatia012ecff2013-10-09 10:56:06 -0400120 try:
Sapan Bhatia9faf7b02013-10-09 10:27:14 -0400121 return self.client_id
Sapan Bhatia012ecff2013-10-09 10:56:06 -0400122 except AttributeError:
Sapan Bhatia9faf7b02013-10-09 10:27:14 -0400123 self.client_id = base64.urlsafe_b64encode(os.urandom(12))
124 return self.client_id
Scott Bakerc1c45f82014-01-21 16:23:51 -0800125
Sapan Bhatia9faf7b02013-10-09 10:27:14 -0400126 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
Sapan Bhatia66f4e612013-07-02 12:12:38 -0400129
Sapan Bhatia9faf7b02013-10-09 10:27:14 -0400130 try:
131 user = Config().feefie_client_user
132 except:
133 user = 'pl'
Sapan Bhatiab9c59342013-09-03 10:21:13 -0400134
Sapan Bhatia9faf7b02013-10-09 10:27:14 -0400135 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()