borgend.py

Sun, 28 Jan 2018 19:27:34 +0000

author
Tuomo Valkonen <tuomov@iki.fi>
date
Sun, 28 Jan 2018 19:27:34 +0000
changeset 87
a214d475aa28
parent 85
56a000d15965
child 89
51cc2e25af38
permissions
-rwxr-xr-x

Better recovery from errors; fixes to potential race conditions in scheduler and repository queue

#!/usr/local/bin/python3

# Common modules
import os
import sys
import argparse
import platform
import logging
# Own modules needed at this stage
import borgend.branding as branding
import borgend.locations as locations

#
# Argument processing
#

parser=argparse.ArgumentParser(
    description=branding.appname_stylised + ": BorgBackup scheduler, queue, and tray icon.",
    epilog='Configuration file location:\n\n    %s\n ' % locations.cfgfile,
    formatter_class=argparse.RawDescriptionHelpFormatter)

parser.add_argument(
    '--no-tray',
    dest='notray',
    action='store_true',
    help='Do not show the tray icon')

parser.add_argument(
    '--debug',
    dest='debug',
    action='store_true',
    help='Set logging level to debug')

args=parser.parse_args()

#
# Done parsing args, import our own modules, and launch everything
#

import borgend.config as config
import borgend.dreamtime as dreamtime
import borgend.loggers as loggers
from borgend.scheduler import Scheduler
from borgend.repository import Repository
from borgend.backup import Backup

logger=loggers.mainlogger

if args.debug:
    logger.setLevel(logging.DEBUG)

tray = None
repos=[]
backups=[]

try:
    dreamtime.start_monitoring()

    scheduler = Scheduler()
    scheduler.start()

    repoconfigs=config.settings['repositories']

    logger.info('Initialising repositories')
    for i in range(len(repoconfigs)):
        r=Repository(i, repoconfigs[i])
        repos.append(r)

    backupconfigs=config.settings['backups']

    logger.info('Initialising backups')
    for i in range(len(backupconfigs)):
        b=Backup(i, backupconfigs[i], scheduler)
        backups.append(b)

    if args.notray or platform.system()!='Darwin':
        # Wait for scheduler to finish
        run=scheduler.join
    else:
        # This is needed for Ctrl+C to work.
        # TODO: proper exit handler, which seems to require
        # ditching/forking/extending rumps to extend the NSApp class
        from PyObjCTools.AppHelper import installMachInterrupt
        installMachInterrupt()
        # Start UI, and let it handle exit control
        from borgend.ui import BorgendTray
        tray=BorgendTray(backups);
        run=tray.run

    for r in repos:
        r.start()

    for b in backups:
        b.start()

    run()

except Exception as err:
    # TODO: Should write errors here to stderr;
    # perhaps add an extra stderr logger for error level messages
    logger.exception("Exception fell through: exiting")

finally:
    logger.debug("Exiting")

    for b in backups:
        b.terminate()

    for r in repos:
        r.terminate()

    if tray:
        tray.quit()
    else:
        logging.shutdown()

mercurial