Files
IKAR/ikar_server/backup.py
T

28 lines
1.4 KiB
Python

"""Consistent SQLite backup plus attachment files; only IKAR paths are used."""
from pathlib import Path
import datetime, os, sqlite3, tarfile, tempfile
root = Path('/mnt/data/ikar_server')
if not os.path.ismount('/mnt/data'):
raise SystemExit('External disk is not mounted')
source = root / 'shared/data'
stamp = datetime.datetime.now(datetime.timezone.utc).strftime('%Y%m%dT%H%M%SZ')
destination = root / f'backups/ikar-{stamp}.tar.gz'
with tempfile.TemporaryDirectory(prefix='backup-', dir=root / 'backups') as temp:
database = Path(temp) / 'ikar.db'
with sqlite3.connect(f'file:{source / "ikar.db"}?mode=ro', uri=True) as live, sqlite3.connect(database) as backup:
live.backup(backup)
if backup.execute('pragma quick_check').fetchone()[0] != 'ok':
raise SystemExit('Database backup failed integrity check')
with tarfile.open(destination, 'w:gz') as bundle:
bundle.add(database, arcname='data/ikar.db')
for directory in source.iterdir():
if directory.is_dir() and directory.name not in ('QlyraUploads', 'AppUpdates'):
bundle.add(directory, arcname=f'data/{directory.name}')
os.chmod(destination, 0o600)
cutoff = datetime.datetime.now(datetime.timezone.utc).timestamp() - 14 * 86400
for previous in (root / 'backups').glob('ikar-*.tar.gz'):
if previous != destination and previous.is_file() and previous.stat().st_mtime < cutoff:
previous.unlink()
print(destination)