#!/usr/bin/env python3 import json import subprocess import os from pathlib import Path import backup_manager def read_config(): source_path = Path(__file__).resolve() nextcloud_secret = source_path.parent / "secrets/nextcloud.json" with open(nextcloud_secret, "r") as f: config = json.load(f) return config class NextcloudManager(backup_manager.BackupManager): def __init__(self, config): super().__init__(config=config) def enable_maintenance(self): cmd = "docker compose exec -i --user 1000:1000 app /var/www/html/occ maintenance:mode --on" try: result = subprocess.run( cmd, shell=True, text=True, check=True, capture_output=True ) except subprocess.CalledProcessError as e: self._gotify.send_subprocess_error( title="Enabling maintenance failed.", error=e ) return False if "Maintenance mode already enabled" in result.stdout: title = "Maintenance unexpectedly enabled" text = ( "Maintenance mode was already enabled. " "Did not expect that. Will continue." ) self._gotify.send_warning(title, text) return True def disable_maintenance(self): cmd = "docker compose exec -i --user 1000:1000 app /var/www/html/occ maintenance:mode --off" try: result = subprocess.run( cmd, shell=True, text=True, check=True, capture_output=True ) except subprocess.CalledProcessError as e: self._gotify.send_subprocess_error("Disabling maintenance failed", e) return False if "Maintenance mode already disabled" in result.stdout: title = "Maintenance mode unexpectedly already disabled" text = ( "Maintenance mode was already disabled. " "Did not expect that. Will continue." ) self._gotify.send_warning(title, text) return True def dump_database(self): password = self._common["MYSQL_PASSWORD"] user = self._common["MYSQL_USER"] db = self._common["MYSQL_DB"] cmd = f"docker compose exec -i --user 1000:1000 db mariadb-dump --single-transaction --default-character-set=utf8mb4 -h localhost -u {user} --password={password} {db} > db/nextcloud.sql" try: result = subprocess.run( cmd, shell=True, check=True, text=True, capture_output=True, ) except subprocess.CalledProcessError as e: self._gotify.send_subprocess_error("Dumping database failed", e) return False self._gotify.send_success("Database dumped", result) return True def main(): config = read_config() os.chdir(config["common"]["BACKUP_DOCKER_DIR"]) backup_manager = NextcloudManager(config) if not backup_manager.enable_maintenance(): backup_manager.disable_maintenance() exit(1) if not backup_manager.dump_database(): backup_manager.disable_maintenance() exit(1) if not backup_manager.borg_backup(): backup_manager.disable_maintenance() exit(1) if not backup_manager.disable_maintenance(): exit(1) exit(0) if __name__ == "__main__": main()