from crontab import CronTab import random import re import sys import json import os import datetime import syslog from django.apps import apps DJANGO_IP = "127.0.0.1:8000" for arg in sys.argv: if re.search('(((1?[0-9]{1,2})|(2[0-4]\d)|(25[0-5]))\.){3}((1?[0-9]{1,2})|(2[0-4]\d)|(25[0-5]))', arg): DJANGO_IP = arg class Task(object): """ Class that contain utils for the cron tasks Attributes ---------- ID_LENGTH: int Length of id string. """ ID_LENGTH = 10 @classmethod def create(cls, period): """ Parse period and create task id. Parameters ---------- period: str Cron formatted string. Returns ------- _id: str Id of task cron_period_string: str Cron formatted string. Examples -------- >>> #Creating a task that runs every minute: >>> _id, cron_period_string = Task.create('minute.every(1)') >>> print(_id, cron_period_string) IoVbRe minute.every(1) >>> #Creating a task that runs every month: >>> _id, cron_period_string = Task.create('minute.month(1)') >>> print(_id, cron_period_string) IoVbRe minute.month(1) >>> #Creating a task that runs every 2 month >>> _id, cron_period_string = Task.create('minute.month(2)') >>> print(_id, cron_period_string) IoVbRe minute.month(2) """ _id = cls.create_id() cron_period_string = cls.parse_period(period) return _id, cron_period_string @classmethod def parse_period(cls, period): """ Method to parse own schedule structure. #TODO Parameters ---------- period: str Cron formatted string. Returns ------- period: str Cron formatted string. """ return period @classmethod def create_id(cls): """ Create random string id of length `Task.ID_LENGTH` from `possible`. Exists len(`possible`)*`Task.ID_LENGTH` (3.40506e^16) combinations. Returns ------- string: str Random id string. """ possible = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"#$¿&/=¡-_+<>' string = ''.join(random.sample(possible, cls.ID_LENGTH)) return string @staticmethod def get_last_run(user, task): """ Get last run of a given task. Seek over /var/log/syslog cron processes and then filter it by user and task id. Parameters ---------- user: str Task user task: str Task id Returns ------- last_run: str Last run date. Format: Month Day Time """ last_run = None for line in open('/var/log/syslog', 'r').readlines(): if re.search('CRON', line): # Replace regex special characters user_taskid = r'{}:{}'.format(user, task) user_taskid = user_taskid.replace('¿', '\¿') user_taskid = user_taskid.replace('+', '\+') user_taskid = user_taskid.replace('%', '\%') user_taskid = user_taskid.replace(')', '\)') user_taskid = user_taskid.replace('(', '\(') if re.search(user_taskid, line): last_run = line[0:15] return last_run @staticmethod def clean_string(string): """ Method to clean some special characters Parameters ---------- string: str String to clean Returns ------- string: str Cleaned string """ string = string.replace('$', '\$') string = string.replace('+', '\+') string = string.replace('%', '\%') string = string.replace(')', '\)') string = string.replace('(', '\(') return string def post(user=None, geom=None, params=None, period=None): """ Create a geomicroservice routine Parameters ---------- user : str User id geom : str Geomicroservice in URL format params : dict Dict containing the parameters to feed `geom` geomicroservice period : str Cron formatted string scheduling the task Returns ------- result : dict Dict containing task_id field with id of created task Notes ----- % in any of string make script falls. Examples -------- >>> import requests >>> import json >>> ints = list(open('AOI_TEST.kml', 'rb').read()) >>> date = '02/18' >>> params = {"user": 'test', "geom": 'MG/update/staticBase', "params": {"user": 'I6', "base": 'sentinel', "params": {"AOI": ints,"date": date}}, "period": 'minute.every(1)'} >>> requests.post(url='/MG/routines/create', json=params) {'task_id':'oij89&!0'} """ check_user = True user = Task.clean_string(user) user_cron = CronTab(user=True) task_id, cron_period_string = Task.create(period) # params['user'] = Task.clean_string(params['user']) command = r'{} {}/cronGeomExecute.py {} {} "{}"'.format(sys.executable,apps.get_app_config('routines').path, geom, DJANGO_IP,params) os.system(command) syslog.syslog(r'CRON {}:{}'.format(user, task_id)) new_task = user_cron.new(command=command, comment=r'{}:{}'.format(user, task_id)) eval('new_task.{}'.format(cron_period_string)) user_cron.write() results = {'task_id': task_id} return results