CrontabManager.py 3.7 KB

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