CrontabManager.py 3.8 KB

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