CrontabManager.py 3.7 KB

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