diff options
author | xengineering <me@xengineering.eu> | 2021-10-06 08:43:07 +0200 |
---|---|---|
committer | xengineering <me@xengineering.eu> | 2021-10-07 07:50:36 +0200 |
commit | 5220b95a03db1edc348d719c683d179962acd0d5 (patch) | |
tree | ddb8053091e1861837047901f585b1b9fa679a05 | |
parent | e5aeb1b18945868ef21c63f1e1dfbb46408acb58 (diff) | |
download | xbackup-5220b95a03db1edc348d719c683d179962acd0d5.tar xbackup-5220b95a03db1edc348d719c683d179962acd0d5.tar.zst xbackup-5220b95a03db1edc348d719c683d179962acd0d5.zip |
Implement manual Backup
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | README.md | 9 | ||||
-rw-r--r-- | config/debug.json | 21 | ||||
-rw-r--r-- | config/default.json | 20 | ||||
-rw-r--r-- | src/debug.py | 2 | ||||
-rw-r--r-- | src/xbackup/backup.py | 100 | ||||
-rw-r--r-- | src/xbackup/config.py | 2 | ||||
-rw-r--r-- | src/xbackup/script.py | 37 |
8 files changed, 181 insertions, 12 deletions
@@ -1 +1,3 @@ **/__pycache__ +backups +fakeroot @@ -7,7 +7,8 @@ This is a convenience wrapper around the Borg backup tool. ## Expected Environment -This tool is designed for Arch Linux. Because it is written in Python and has minimal dependencies it should be easy to adapt it to other Linux distributions. +This tool is designed for Arch Linux. Because it is written in Python and has +minimal dependencies it should be easy to adapt it to other Linux distributions. ## Installation @@ -20,13 +21,15 @@ cd xbackup/archlinux make install ``` -This will create the Arch Linux package for xbackup and installs it as a foreign / unofficial package (like the AUR packages). +This will create the Arch Linux package for xbackup and installs it as a +foreign / unofficial package (like the AUR packages). ## Done / Features (Last finished task first) +- [x] manual backup functionality / MVP - [x] config parsing - [x] argument parsing - [x] implement Arch Linux Packaging @@ -37,8 +40,6 @@ This will create the Arch Linux package for xbackup and installs it as a foreign (Highest priority first) -- [ ] manual backup functionality / MVP -- [ ] software list file support (generates list of all linux packages) - [ ] XMPP notification via [xbot](https://gitea.xengineering.eu/xengineering/xbot) - [ ] MariaDB fullbackup - [ ] backup systemd daemon diff --git a/config/debug.json b/config/debug.json new file mode 100644 index 0000000..948b432 --- /dev/null +++ b/config/debug.json @@ -0,0 +1,21 @@ +{ + "backup":{ + "backup_source":"fakeroot", + "borg_repos_folder":"fakeroot/var/lib/xbackup/borg", + "blacklist":[ + "dev/*", + "lost+found/*", + "media/*", + "mnt/*", + "proc/*", + "run/*", + "sys/*", + "tmp/*" + ], + "keep-hourly":null, + "keep-daily":7, + "keep-weekly":4, + "keep-monthly":6, + "keep-yearly":null + } +} diff --git a/config/default.json b/config/default.json index 2bfd471..fd0b5b4 100644 --- a/config/default.json +++ b/config/default.json @@ -1,3 +1,21 @@ { - "test":4 + "backup":{ + "backup_source":"/", + "borg_repos_folder":"/var/lib/xbackup/borg", + "blacklist":[ + "dev/*", + "lost+found/*", + "media/*", + "mnt/*", + "proc/*", + "run/*", + "sys/*", + "tmp/*" + ], + "keep-hourly":null, + "keep-daily":7, + "keep-weekly":4, + "keep-monthly":6, + "keep-yearly":null + } } diff --git a/src/debug.py b/src/debug.py index f075e25..6daa264 100644 --- a/src/debug.py +++ b/src/debug.py @@ -1,5 +1,5 @@ #!/usr/bin/python3 -# vim: shiftwidth=4 tabstop=4 expandtab +# vim: shiftwidth=4 softtabstop=4 tabstop=4 expandtab """A Debug Script for Development Purposes""" diff --git a/src/xbackup/backup.py b/src/xbackup/backup.py new file mode 100644 index 0000000..b56e0cc --- /dev/null +++ b/src/xbackup/backup.py @@ -0,0 +1,100 @@ +#!/usr/bin/python3 +# vim: shiftwidth=4 softtabstop=4 tabstop=4 expandtab + + +"""Backup Functionality of xbackup""" + + +import os +import sys +import subprocess + + +def backup(config): + """perform a file-based full system backup""" + + # generate all necessary paths based on config + paths = Filepaths(config) + print(paths) + + # init borg repository (accepting failure on already existing repo) + shell("borg init -e none {}".format(paths.borg_repo), panic=False) + + # run backup + command = "borg create -v --stats --compression zstd \\" + command += """ + {repo}::'{{hostname}}-{{user}}-{{now:%Y-%m-%d_%H:%M:%S}}' \\""".format( + repo=paths.borg_repo + ) + command += "\n {} \\".format(paths.backup_source) + for key,value in enumerate(paths.blacklist): + command += "\n --exclude '{}'".format(value) + if key != len(paths.blacklist) -1: + command += " \\" + + shell(command) + + +class Filepaths(object): + """A Container Class to hold Filepaths for the Borg Backup Tool""" + + def __init__(self, config): + """The Constructor""" + + # parse backup source (usually / for system backups) + self.backup_source = config["backup_source"] + + # + self.borg_repos_folder = config["borg_repos_folder"] + + # path to the borg repository + hostname = os.uname()[1] + self.borg_repo = os.path.join(self.borg_repos_folder, hostname) + + # create blacklist of folders to be excluded from the backup + self.blacklist = [] + for entry in config["blacklist"]: + self.blacklist.append(os.path.join(self.backup_source, entry)) + + # avoid matroska-style backups of backups (yes, it is important) + self.blacklist.append(self.borg_repos_folder) + + def __str__(self): + """Converts an Object based on this Class to a String""" + + retval = "" + + retval += "\nbackup_source:\n" + self.backup_source + "\n" + + retval += "\nblacklist:\n" + for item in self.blacklist: + retval += item + "\n" + + retval += "\nborg_repo:\n" + self.borg_repo + "\n" + + return retval + + +def shell(command, panic=True): + """Savely execute a Shell Command + + - set panic=False to continue with execution on non-zero return code + """ + + # print command + print("\nExecuting '" + command + "' ...") + + # command execution + return_code = subprocess.call(command, shell=True) + + # handle non-zero return code + if return_code != 0 and panic: + print("Command '{}'\nfailed with return code {}".format( + command, + str(return_code) + )) + sys.exit(return_code) + + # final message and return + print("... done!") + return diff --git a/src/xbackup/config.py b/src/xbackup/config.py index 1e115a5..4c72915 100644 --- a/src/xbackup/config.py +++ b/src/xbackup/config.py @@ -1,5 +1,5 @@ #!/usr/bin/python3 -# vim: shiftwidth=4 tabstop=4 expandtab +# vim: shiftwidth=4 softtabstop=4 tabstop=4 expandtab """Module for Configuration Parsing Functionality of xbackup""" diff --git a/src/xbackup/script.py b/src/xbackup/script.py index b69da00..c8e619b 100644 --- a/src/xbackup/script.py +++ b/src/xbackup/script.py @@ -1,5 +1,5 @@ #!/usr/bin/python3 -# vim: shiftwidth=4 tabstop=4 expandtab +# vim: shiftwidth=4 softtabstop=4 tabstop=4 expandtab """Module for the Script Functionality of xbackup""" @@ -10,6 +10,7 @@ import time import sys from xbackup import config +from xbackup import backup def run(): @@ -18,15 +19,16 @@ def run(): args = parse_arguments() cfg = config.get(args.config) + welcome() + if args.command == "backup": - print("Performing dummy backup based on '{}'".format(args.config)) - print("Config is:\n{}".format(config.dump(cfg))) - time.sleep(1) - print("Done!") + backup.backup(cfg["backup"]) else: print("Unknown command '{}'".format(args.command)) sys.exit(1) + bye() + def parse_arguments(): """handles argument parsing with the argparse module""" @@ -53,3 +55,28 @@ def parse_arguments(): # argument parsing args = parser.parse_args() return args + + +def welcome(): + """Print Welcome Text""" + + print(""" +################################################################################ + _ _ + __ _| |__ __ _ ___| | ___ _ _ __ + \ \/ / '_ \ / _` |/ __| |/ / | | | '_ \ + > <| |_) | (_| | (__| <| |_| | |_) | + /_/\_\_.__/ \__,_|\___|_|\_\\\\__,_| .__/ + |_| + +################################################################################ +""", end="") + + +def bye(): + """Print final Text""" + + print(""" +################################################################################ + +""", end="") |