python-backup/backup.py

152 lines
4.7 KiB
Python
Raw Permalink Normal View History

import os
import sched
import time
import sys
from termcolor import colored, cprint
import getpass
import json
import datetime
import uuid
import logging
import logging.handlers
import multiprocessing
syslog = True
debug = False
config_path = '/etc/python-backup.json'
Config = None
###############
# Helpers #
###############
def log(message):
if debug:
cprint('[DEBUG]: %s' % message, 'yellow')
def error(message):
cprint('[ERROR]: %s' % message, 'white', 'on_red')
def printHelp():
cprint(
'Please run backup.py like so:\n~$ python3 ./backup.py\t\t\tRun with default configuration file (/etc/python-backup.json)\n\
or\n~$ python3 ./backup.py {parameter}\n\
-h (--help)\t\t\tShow help\n\
-v (--version)\t\t\tShow script version\n\
-d (--debug)\t\t\tShow debug messages\n\
-c (--config) [PATH]\t\tConfiguration file path\n\
--single\t\t\tRun single backup - otherwise run in daemon mode\n', 'cyan')
def printVersion():
cprint('Python-backup version 1.0\nBy Dominik Dancs | email> do@dancs.sk | web> https://do.dancs.sk', 'cyan')
exit(0)
def loadConfig():
global config_path, Config, syslog
try:
Config = json.load(open(config_path))
try:
Config['syslog']
if isinstance(Config['syslog'], bool) and not Config['syslog']:
syslog = False
Config['unit-name']
Config['to-backup']
if not isinstance(Config['to-backup'], list):
raise Exception('Paths to backup must be a list!')
for location in Config['to-backup']:
location['path']
location['name']
Config['compression-level']
if not isinstance(Config['compression-level'], int) or Config['compression-level'] < 0 or Config['compression-level'] > 9:
raise Exception(
'Compression level must be a number between 0 - 9!')
Config['cpu-threads']
if not isinstance(Config['cpu-threads'], int):
raise Exception('Number of CPU threads must be a number!')
if Config['cpu-threads'] < 1 or Config['cpu-threads'] > multiprocessing.cpu_count():
raise Exception('Invalid number of CPU threads!')
Config['backup-locations']
if not isinstance(Config['backup-locations'], list):
raise Exception('Backup locations must be a priority list!')
for location in Config['backup-locations']:
location['path']
location['priority']
if not isinstance(location['priority'], int) or location['priority'] < 0 or location['priority'] > 999:
raise Exception(
'Location priority must be a number from 0 - 999')
except Exception as e:
if e == 'syslog':
error('Please specify unit name!')
if e == 'unit-name':
error('Please specify unit name!')
elif e == 'to-backup':
error('Please specify paths to backup!')
elif e == 'compression-level':
error('Please specify compression level (0-9)!')
elif e == 'cpu-threads':
error('Please specify number of available CPU threads!')
elif e == 'backup-locations':
error('Please specify backup locations!')
else:
error('Config file does not follow standards!')
log(e)
exit(1)
except Exception as e:
error('Unable to read config file!')
exit(1)
########################
# Argument parsing #
########################
# not enough parameters supplied - show help
if len(sys.argv) > 0:
i = 1
while i < len(sys.argv):
arg = sys.argv[i]
i += 1
if arg == '-h' or arg == '--help':
printHelp()
exit(0)
if arg == '-v' or arg == '--version':
printVersion()
exit(0)
if arg == '-d' or arg == '--debug':
debug = True
elif arg == '-c' or arg == '--config':
try:
config_path = sys.argv[i]
i += 1
except:
error('No config file provided!')
printHelp()
exit(1)
else:
error('Unrecognized argument')
printHelp()
exit(1)
loadConfig()
########################
# Setup syslog #
########################
if syslog:
logger = logging.getLogger('python-backup')
handler = logging.handlers.SysLogHandler(address='/dev/log')
handler.setFormatter(logging.Formatter(
'%(name)s: [%(levelname)s] %(message)s'
))
logger.addHandler(handler)