def run(self): """ Start observers for the given rules. """ logger.debug("Starting agent.") mon_thread = None try: while True: if RippleConfig().new_rules: # I need to use a stoppable thread or make # the thread set the observer to stop if mon_thread is not None: mon_thread = None # the watchdog monitor is blocking, so we need # to start it as a thread in order to restart it # when new rules are detected mon_thread = threading.Thread(target=self.set_observers) mon_thread.daemon = True mon_thread.start() RippleConfig().new_rules = False time.sleep(15) except KeyboardInterrupt: try: self.watchdog_ob.stop() self.watchdog_ob.join() except: pass
def monitor(self): # Set up the event handler event_handler = MyEventHandler(patterns=['*'], ignore_patterns=['version.py'], ignore_directories=True) event_handler.setup(self) # Extract the set of directories to listen to listen_dirs = self.get_dirs_to_monitor() # Create an observer and schedule each of the directories self.observer = Observer() logger.debug("Starting observer: %s" % RippleConfig().monitor) if RippleConfig().monitor == "poll": self.observer = PollingObserver() for d in listen_dirs: # Put this in a try so it doesn't crash if the dir doesnt exist if os.path.isdir(d): logger.info("Monitoring: %s" % d) self.observer.schedule(event_handler, d, recursive=True) else: logger.error("Directory does not exist: %s" % d) try: self.observer.start() while True: time.sleep(1) except KeyboardInterrupt: self.stop_monitoring() self.observer.join()
def check_rules(self, event): """ Try to match a rule to this event. If nothing is found, return None """ logger.debug("Checking rules") event_data = event.split(" ") fid = '' eid = event_data[0] self.last = eid event_type = event_data[1] src_path = '' for e in event_data: if 't=[' in e: fid = e[e.find("[") + 1:e.find("]")] if fid not in self.events: # lfs fid2path /mnt/scratch 0x200000401:0x5:0x0 src_path = subprocess.check_output( ["lfs", "fid2path", self.lustre_path, fid]) # Extract the file and path names # src_path = os.path.abspath(event.src_path) event_path = src_path.rsplit(os.sep, 1)[0] file_name = src_path.rsplit(os.sep, 1)[1] # Iterate through rules and try to apply them for rule in RippleConfig().rules[:]: if self.match_condition(event_type, event_path, file_name, rule): send_event = { 'event': { 'type': event_type, 'pathname': src_path, 'path': event_path, 'name': file_name, 'uuid': str(uuid.uuid4()), 'hash': 'hashvalue' } } send_event.update(rule) # check if it is a gcmd, if so, replace the action if re.match(file_name, '.*.gcmd'): action = self.get_cmd(src_path) if action: send_event.update(action) # Set a target for this rule # send_event = self.set_target(send_event) # Now push it down the queue message = json.dumps(send_event) RippleConfig().queue.put(message) logger.debug("Sent data to queue") # self.add_event_to_db(send_event) # Check if it is a new set of rules to load # if rule['action']['type'] == 'rules': # if rule['action']['process']: # self.load_rules(src_path) return None
def check_rules(self, event): """ Try to match a rule to this event. If nothing is found, return None """ #logger.debug("Checking rules") # Extract the file and path names src_path = os.path.abspath(event.src_path) event_path = src_path.rsplit(os.sep, 1)[0] file_name = src_path.rsplit(os.sep, 1)[1] # if 'glink' in file_name: # return # Iterate through rules and try to apply them for rule in RippleConfig().rules[:]: # We are potentially monitoring multiple paths, so check if the # rule should be applied to a file in this path (or subpath). event_type = type(event).__name__ if self.match_condition(event_type, event_path, file_name, rule): # The filename matches the trigger regex -- now build # an event to send to lambda # TODO: add a has of these values so i know it is unique # m = hashlib.md5() send_event = { 'event': { 'type': type(event).__name__, 'pathname': src_path, 'path': event_path, 'name': file_name, 'uuid': str(uuid.uuid4()), 'hash': 'hashvalue' } } send_event.update(rule) # check if it is a gcmd, if so, replace the action if re.match(file_name, '.*.gcmd'): action = self.get_cmd(src_path) if action: send_event.update(action) # Set a target for this rule # send_event = self.set_target(send_event) # Now push it down the queue message = json.dumps(send_event) RippleConfig().queue.put(message) logger.debug("Sent data to queue") return None
def poll_for_jobs(self): """ Without an API to accept jobs, reach out to the cloud API and request jobs for this endpoint. """ payload = {'Endpoint': RippleConfig().endpoint_id} data = {} try: r = requests.post(RippleConfig().get_jobs_path, data=payload) data = json.loads(r.text) except Exception as e: logger.error("Did not receive proper json when polling for jobs.") logger.error(e) # logger.debug("Runner: polled new job: %s" % data) return data
def get_rules(): """ Load the rules for this agent. """ # threading.Timer(10.0, get_rules).start() while True: RippleConfig().load_rules() time.sleep(30)
def report_job(self, job): """ Report the job has been run. """ logger.debug("Reporting job.") payload = { 'endpoint_uuid': RippleConfig().endpoint_id, 'status_code': 'COMPLETE', 'status_message': 'run', 'event': job, 'job_id': job['job_id'], 'output': job['output'], 'err': job['err'] } logger.debug(payload) r = requests.post(RippleConfig().update_status_path, json=payload) data = json.loads(r.text) return data
def check_rules(self, event): """ Try to match a rule to this event. If nothing is found, return None They look like this: key shmid owner perms bytes nattch status 0x00000000 262145 ryan 600 393216 2 dest """ logger.debug("Checking rules") # Iterate through rules and try to apply them for rule in RippleConfig().rules[:]: event_type = event['type'] if self.match_condition(event_type, rule): # Currently putting in pathname as key, need to # think of a better way to handle "other" information send_event = { 'event': { 'type': event_type, 'size': event['bytes'], 'key': event['key'], 'pathname': event['key'], 'path': event['key'], 'name': event['key'], 'shmid': event['shmid'], 'perms': event['perms'], 'owner': event['owner'], 'status': event['status'], 'uuid': str(uuid.uuid4()), 'hash': 'hashvalue' } } print("Sending event: %s" % send_event) send_event.update(rule) # Now push it down the queue message = json.dumps(send_event) RippleConfig().queue.put(message) logger.debug("Sent data to queue") return None
def get_dirs_to_monitor(self): """ Work out which directories to monitor. """ rules = RippleConfig().rules listen_dirs = [] for rule in rules: if rule['trigger']['monitor'] == 'filesystem': listen_dirs.append(rule['trigger']['parameters']['directory']) listen_dirs = list(set(listen_dirs)) logger.debug("Monitoring dirs: %s" % listen_dirs) return listen_dirs
def set_observers(self): """ Set the observers. """ try: self.watchdog_ob.stop() self.watchdog_ob.join() except Exception: pass mon = RippleConfig().monitor if mon == "inotify" or mon == "poll": self.watchdog_ob = PosixObserver() self.watchdog_ob.monitor() elif mon == "lustre": self.lustre_mon = LustreObserver() self.lustre_mon.monitor() elif mon == "ipc": self.ipc_mon = IPCObserver() self.ipc_mon.monitor()
def run(self): """ Execute jobs. """ # Because this doesn't have an API for the cloud # to submit jobs, start by polling for new ones. self.executions = [] while True: self.jobs = self.poll_for_jobs() for job in self.jobs: try: job = json.loads(job) if job['event_uuid'] not in self.completed_jobs: result = self.execute_job(job) self.record_finished_job(job, result) except Exception as e: logger.error("Failed to execute job.") logger.error(job) logger.error(e) time.sleep(float(RippleConfig().runner_poll_rate))
def __init__(self): RippleConfig()
def __init__(self): RippleConfig() self.completed_jobs = []