From 8ed5263984a75644b10c0a7f686ff8ffed8d8daa Mon Sep 17 00:00:00 2001 From: dave Date: Tue, 25 Jul 2023 16:58:09 -0700 Subject: [PATCH] log timestamps instead of a simple touch --- resticbackup/cli.py | 11 +++++------ resticbackup/lib.py | 23 +++++++++++++++++------ resticbackup/types.py | 10 +++++----- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/resticbackup/cli.py b/resticbackup/cli.py index e0f3285..aabba96 100644 --- a/resticbackup/cli.py +++ b/resticbackup/cli.py @@ -1,11 +1,10 @@ import os import argparse import subprocess -from socket import getfqdn from resticbackup.types import ClientConfig, load_config, load_base_config, list_configs from resticbackup.lib import ExecWrapper, init_ok, die, pdie, checkp, get_retention_args, \ - get_newest_snapshot, touch_statefile + get_newest_snapshot, update_statefile def cmd_backup(args, parser): @@ -55,10 +54,10 @@ def cmd_backup(args, parser): # perform junk deletion checkp(config.run(["prune"])) - # touch if necessary - if config.touch_complete: - path = config.touch_complete.format(name=args.name) - touch_statefile(path) + # update statefile if configured + if config.statefile: + path = config.statefile.format(name=args.name) + update_statefile(path) def cmd_restore(args, parser): diff --git a/resticbackup/lib.py b/resticbackup/lib.py index 15bcbd1..972a060 100644 --- a/resticbackup/lib.py +++ b/resticbackup/lib.py @@ -1,6 +1,7 @@ import os import sys import json +import time import subprocess @@ -127,12 +128,22 @@ def get_retention_args(schedule): raise Exception("unknown retention function {}".format(mode)) -def touch_statefile(path): +def update_statefile(path): + """ + the statefile contains a json list of timestamps of the last 10 times the backup completed + """ d = os.path.dirname(path) if not os.path.exists(d): os.makedirs(d) - if os.path.exists(path): - os.utime(path) - else: - with open(path, "w"): - pass + + try: + with open(path) as f: + state = json.load(f) + except (json.decoder.JSONDecodeError, FileNotFoundError): + state = [] + + state.append(int(time.time())) + state = state[0:10] + + with open(path, "w") as f: + json.dump(state, f) diff --git a/resticbackup/types.py b/resticbackup/types.py index 672f434..8554f76 100644 --- a/resticbackup/types.py +++ b/resticbackup/types.py @@ -67,7 +67,7 @@ class ClientConfig: server_type: str uri: str secret: str - touch_complete: str + statefile: str backup: BackupConfig @property @@ -90,14 +90,14 @@ class ClientConfig: server_type, server = main["server"].split(":", 1) if server_type != "s3": raise Exception("unsupported server type: {}".format(server_type)) - touch_path = main.get("touch_complete") - if touch_path is not None and not touch_path.startswith("/"): - raise Exception("touch path must be absolute: {}".format(touch_path)) + statefile = main.get("statefile") + if statefile is not None and not statefile.startswith("/"): + raise Exception("statefile path must be absolute: {}".format(statefile)) return ClientConfig( server_type=server_type, uri=urlparse(server), secret=main["secret"], - touch_complete=touch_path, + statefile=statefile, backup=backup )