creole/schedule/schedule

218 lines
6.1 KiB
Python
Executable File

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
utilitaire de lancement en fonction
- cron
- bareos
"""
import sys
import time
from os import readlink, unlink
from os.path import join
from glob import glob
from pyeole.process import system_out
from pyeole.schedule import SCHEDULE_DIR
from pyeole.bareos import is_running_jobs, bareos_get_jobs_list
from creole.client import CreoleClient
from pyeole.i18n import i18n
from pyeole.log import init_logging
_ = i18n('eole-schedule')
log = init_logging(name=u'eole-schedule', level='info', syslog=True,
console=['stdout', 'stderr'])
client = CreoleClient()
NOW = time.strftime('%d/%m/%y %H:%M', time.localtime())
# day in month
MONTH_DAY = int(time.strftime('%d', time.localtime()))
# day in week
WEEK_DAY = int(time.strftime('%w', time.localtime()))
HOUR = int(time.strftime('%H', time.localtime()))
# night start at 12
if HOUR > 12:
WEEK_DAY += 1
if WEEK_DAY == 0:
# sunday is 7
WEEK_DAY = 7
if WEEK_DAY == 8:
WEEK_DAY = 1
def log_parts(func):
def split(msg):
shreds = msg.split('\n')
return [func(shred) for shred in shreds if len(shred) > 0]
return split
log.info = log_parts(log.info)
log.error = log_parts(log.error)
log.warning = log_parts(log.warning)
def run_runparts(mode, bareos_type):
"""
run part script
test if weekly or monthly script must be launched this day
"""
if mode == 'weekly' and WEEK_DAY != client.get('/schedule/schedule/weekday'):
return
if mode == 'monthly' and ( WEEK_DAY != client.get('/schedule/schedule/monthday') or MONTH_DAY > 7 ):
return
part_str = u"{} schedule {}".format(bareos_type, mode)
log.info(_("Starting {}").format(part_str))
dirname = join(SCHEDULE_DIR, mode, bareos_type)
env = {'PATH': '/sbin:/usr/sbin:/bin:/usr/bin:/usr/share/eole',
'LC_ALL': 'fr_FR.UTF-8'}
if mode != 'once':
runparts_cmd = "/bin/run-parts --exit-on-error --report {} --arg {}"
wrapped_runparts_cmd = ['/bin/bash',
'-c',
runparts_cmd.format(dirname, mode)]
ret, out, err = system_out(wrapped_runparts_cmd, env=env)
else:
# unlink script before launch it
# (for example remove 'reboot' link before restart the machine)
names = glob(join(dirname, '*'))
names.sort()
ret = 0
out = None
err = None
for name in names:
script = readlink(name)
unlink(name)
wrapped_runparts_cmd = ['/bin/bash',
'-c', script]
ret, out, err = system_out(wrapped_runparts_cmd, env=env)
if ret != 0:
break
if out:
log.info(out)
if err:
log.error(err)
if ret != 0:
# on affiche sur stderr pour que cron le récupère et le mail
# ce qui est printé sur stdout est envoyé dans les logs
if out:
sys.stderr.write(out)
if err:
sys.stderr.write(err)
sys.stderr.write(_("Error detected\n"))
log.error(_("{} exited with error return code").format(part_str))
sys.exit(ret)
else:
log.info(_("{} finished").format(part_str))
def schedule_pre():
run_runparts('daily', 'pre')
run_runparts('weekly', 'pre')
run_runparts('monthly', 'pre')
run_runparts('once', 'pre')
def schedule_post():
i = 0
while is_running_jobs():
time.sleep(1)
i += 1
if i == 30:
log.info(_("Job already running, cancelling"))
sys.exit(1)
run_runparts('daily', 'post')
run_runparts('weekly', 'post')
run_runparts('monthly', 'post')
run_runparts('once', 'post')
def schedule_cron():
"""
If schedule.py is launched by cron, try to run pre and post
cron file for daily, weekly and monthly if no backup is set this day
"""
def exit_not_cron():
log.info(_("bareos is set for this day, cancelled"))
sys.exit(0)
try:
bareosjobs = bareos_get_jobs_list()
for job in bareosjobs:
day = int(job['day'])
if job['job'] == 'daily':
if day <= WEEK_DAY <= job['end_day']:
exit_not_cron()
elif job['job'] == 'weekly':
if WEEK_DAY == day:
exit_not_cron()
elif job['job'] == 'monthly':
if WEEK_DAY == day and MONTH_DAY < 8:
exit_not_cron()
else:
raise Exception(_('Unknown job: {0}').format(job['job']))
except SystemExit:
raise
except:
pass
run_runparts('daily', 'pre')
run_runparts('daily', 'post')
run_runparts('weekly', 'pre')
run_runparts('weekly', 'post')
run_runparts('monthly', 'pre')
run_runparts('monthly', 'post')
run_runparts('once', 'pre')
run_runparts('once', 'post')
# __________________________________________________
if __name__ == '__main__':
usage = """usage:
{0} bareos [pre|post]
{0} cron""".format(sys.argv[0])
if len(sys.argv) == 1:
print usage
sys.exit(1)
if len(sys.argv) > 3:
log.error(_("Too many arguments: {0}").format(sys.argv))
print usage
sys.exit(1)
mode = sys.argv[1]
if mode == 'bareos':
# pre|post
if len(sys.argv) == 2:
log.error(_("Not enough arguments: {0}").format(sys.argv))
print usage
sys.exit(1)
if sys.argv[2] not in ['pre', 'post']:
log.error(_("Second argument must be pre or post: {0}").format(sys.argv))
print usage
sys.exit(1)
bareos_type = sys.argv[2]
if bareos_type == 'pre':
schedule_pre()
elif bareos_type == 'post':
schedule_post()
elif mode == 'cron':
if len(sys.argv) != 2:
log.error(_("Too many arguments for cron: {0}").format(sys.argv))
print usage
sys.exit(1)
schedule_cron()
else:
log.error(_("Unknown schedule type : {0}").format(mode))
print usage
sys.exit(1)