borgend.py

Sun, 28 Jan 2018 11:04:52 +0000

author
Tuomo Valkonen <tuomov@iki.fi>
date
Sun, 28 Jan 2018 11:04:52 +0000
changeset 78
83b43987e61e
parent 76
4b08fca3ce34
child 79
b075b3db3044
permissions
-rwxr-xr-x

Renamed the "sleep" module "dreamtime"

#!/usr/local/bin/python3

import os
import sys
import logging
import logging.handlers
import argparse
import platform

#
# Branding
#
appname="borgend"
appname_stylised="Borgend"

#
# Logging configuration
#

loglevel=logging.INFO
logfmt="%(asctime)s:%(levelname)s:%(name)s:%(message)s"
fifolog_capacity=1000
fifolog_fmt="%(asctime)s:%(levelname)s:%(message)s"

#
# Setup logger, needed by the config module to be loaded next
#

logger=logging.getLogger(appname)
logger.handlers.clear()
logger.setLevel(loglevel)
stderrlog=logging.StreamHandler()
stderrlog.setLevel(logging.WARNING)
logger.addHandler(stderrlog)
logger.propagate=True

#
# Import our own modules. This needs to be done here
# for the things above to be available to them
#

import config
from scheduler import Scheduler
from fifolog import FIFOHandler
from repository import Repository

#
# Argument processing
#

def do_args():
    parser=argparse.ArgumentParser(
        description=appname_stylised + ': BorgBackup scheduler and tray icon.',
        epilog='Configuration file location:\n\n    %s\n ' % config.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')

    return parser.parse_args()

#
# Main routine
#

# First, setup our own logging handlers
fifolog=FIFOHandler(fifolog_capacity)
logger.addHandler(fifolog)
fifolog.setFormatter(logging.Formatter(fifolog_fmt))

if __name__=="__main__":
    # Parse args. Let argparse handle errors/exit if there are any
    args= do_args()
    tray = None
    repos=[]
    backups=[]

    try:
        args=do_args()

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

        if not os.path.isdir(config.logs_dir):
            os.makedirs(config.logs_dir)

        handler=logging.handlers.TimedRotatingFileHandler(
            os.path.join(config.logs_dir, appname+'.log'),
            when='D', interval=1)
        handler.setFormatter(logging.Formatter(logfmt))
        logger.addHandler(handler)

        from threading import Thread
        from backup import Backup
        from queue import Queue
        import signal, os
        import dreamtime

        dreamtime.start_monitoring()

        scheduler = Scheduler()
        scheduler.start()

        repoconfigs=config.settings['repositories']

        for i in range(len(repoconfigs)):
            logger.info('Setting up repository %d' % i)
            r=Repository(i, repoconfigs[i])
            repos.append(r)

        backupconfigs=config.settings['backups']

        for i in range(len(backupconfigs)):
            logger.info('Setting up backup set %d' % i)
            b=Backup(i, backupconfigs[i], scheduler)
            backups.append(b)

        for r in repos:
            r.start()

        for b in backups:
            b.start()

        if args.notray or platform.system()!='Darwin':
            # Wait for scheduler to finish
            scheduler.join()
        else:
            # Start UI, and let it handle exit control
            from ui import BorgendTray
            tray=BorgendTray(backups);
            tray.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 to outer level: exiting")

    finally:
        for b in backups:
            b.terminate()

        for r in repos:
            r.terminate()

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

    #
    # This shit is fucked, disables ^C etc., and threading doesn't seem to help
    #

    # ui_thread=Thread(target=tray.run)
    # ui_thread.daemon=True
    # ui_thread.start()

    # def quit_signal_handler(signum, frame):
    #     print('Signal handler called with signal %s' % str(signum))
    #     ui_thread.terminate()
    #     os.exit()

    # signal.signal(signal.SIGTERM, quit_signal_handler)
    # signal.signal(signal.SIGINT, quit_signal_handler)

mercurial