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