CrontabManager.py 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. from crontab import CronTab
  2. from crontab import CronSlices
  3. from core.ConfigurationManager.BrainLoader import BrainLoader
  4. from core.Models import Event
  5. import logging
  6. class InvalidCrontabPeriod(Exception):
  7. pass
  8. CRONTAB_COMMENT = "JARVIS"
  9. JARVIS_ENTRY_POINT_SCRIPT = "jarvis.py"
  10. class CrontabManager:
  11. def __init__(self, brain_file=None):
  12. self.my_user_cron = CronTab(user=True)
  13. self.base_command = self._get_base_command()
  14. self.brain = BrainLoader(filename=brain_file).get_brain()
  15. def load_events_in_crontab(self):
  16. """
  17. Remove all line in crontab with the CRONTAB_COMMENT
  18. Then add back line from event in the brain.yml
  19. :return:
  20. """
  21. # clean the current crontab from all jarvis event
  22. self._remove_all_jarvis_job()
  23. # load the brain file
  24. for synapse in self.brain.synapes:
  25. for signal in synapse.signals:
  26. # print signal
  27. # if the signal is an event we add it to the crontab
  28. if type(signal) == Event:
  29. # for all synapse with an event, we add the task id to the crontab
  30. self._add_event(period_string=signal.period, event_id=synapse.name)
  31. def _add_event(self, period_string, event_id):
  32. my_user_cron = CronTab(user=True)
  33. job = my_user_cron.new(command=self.base_command+" "+str("\"" + event_id + "\""), comment=CRONTAB_COMMENT)
  34. if CronSlices.is_valid(period_string):
  35. job.setall(period_string)
  36. job.enable()
  37. else:
  38. raise InvalidCrontabPeriod("The crontab period %s is not valid" % period_string)
  39. # write the file
  40. my_user_cron.write()
  41. def get_jobs(self):
  42. return self.my_user_cron.find_comment(CRONTAB_COMMENT)
  43. def _remove_all_jarvis_job(self):
  44. """
  45. Remove all line in crontab that are attached to JARVIS
  46. :return:
  47. """
  48. iter = self.my_user_cron.find_comment(CRONTAB_COMMENT)
  49. for job in iter:
  50. logging.debug("remove job %s from crontab" % job)
  51. self.my_user_cron.remove(job)
  52. # write the file
  53. self.my_user_cron.write()
  54. # this is a fix for the CronTab lib
  55. # see https://github.com/peak6/python-crontab/issues/1
  56. new_iter = self.my_user_cron.find_comment(CRONTAB_COMMENT)
  57. sum_job = sum(1 for _ in new_iter)
  58. while sum_job > 0:
  59. self._remove_all_jarvis_job()
  60. def _get_base_command(self):
  61. """
  62. Return the path of the entry point of Jarvis
  63. Example: /home/user/jarvis/jarvis.py
  64. :return: The path of the entry point script jarvis.py
  65. """
  66. import inspect
  67. import os
  68. # get current script directory path. We are in /an/unknown/path/jarvis/core
  69. cur_script_directory = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
  70. # get parent dir. Now we are in /an/unknown/path/jarvis
  71. parent_dir = os.path.normpath(cur_script_directory + os.sep + os.pardir)
  72. # we add the jarvis.py file name
  73. real_jarvis_entry_point_path = parent_dir + os.sep + JARVIS_ENTRY_POINT_SCRIPT
  74. # We test that the file exist before return it
  75. logging.debug("Real jarvis.py path: %s" % real_jarvis_entry_point_path)
  76. if os.path.isfile(real_jarvis_entry_point_path):
  77. return real_jarvis_entry_point_path
  78. raise IOError("jarvis.py file not found")