Files
miyagi-backup/testing/python/miyagi-python.py
T
sysops d83c3113f8 testing/: bisherige Testversion inkl. Erweiterungen einchecken
Erstmalig getrackt (war bisher lokal ungetrackt). Enthält gegenüber dem
Root-Stand: PBSPORT, DYNROUTE/DDNS-Konfig, zfs_replace()/wait_replace()
für Resilver-Abwarten vor Shutdown, BatchMode SSH, write_zsync_config()-
Anpassungen (Snapshot-Label-Präfix, checkzfs_spool_maxage).
2026-07-14 13:39:51 +02:00

91 lines
2.9 KiB
Python

#!/usr/bin/env python3
import os, sys, subprocess, logging, time, tempfile, shutil
from pathlib import Path
from datetime import datetime
# === Logging Setup ===
SCRIPT_NAME = Path(sys.argv[0]).stem
LOGFILE = f"/var/log/{SCRIPT_NAME}.log"
logging.basicConfig(
filename=LOGFILE,
level=logging.INFO,
format='[%(asctime)s] %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter('[%(asctime)s] %(message)s', '%Y-%m-%d %H:%M:%S')
console.setFormatter(formatter)
logging.getLogger().addHandler(console)
def log(msg):
logging.info(msg)
# === Config Loader ===
import yaml
CONFIG = {}
def load_config(path):
global CONFIG
if not os.path.isfile(path):
log(f"ERROR: Config file not found: {path}")
sys.exit(1)
with open(path) as f:
CONFIG = yaml.safe_load(f)
log("Config loaded successfully")
# === SSH / SCP Wrappers ===
def rssh(cmd, port=None, host=None):
port = port or CONFIG.get('SOURCEPORT', 22)
host = host or CONFIG.get('SOURCEHOST')
ssh_cmd = ["ssh", "-o", "BatchMode=yes", "-o", "ConnectTimeout=10", "-p", str(port), f"root@{host}"] + cmd
return subprocess.run(ssh_cmd, capture_output=True, text=True)
def rscp(local, remote, port=None, host=None):
port = port or CONFIG.get('SOURCEPORT', 22)
host = host or CONFIG.get('SOURCEHOST')
scp_cmd = ["scp", "-P", str(port), local, f"root@{host}:{remote}"]
return subprocess.run(scp_cmd)
# === Beispiel-Funktionen 1:1 ===
def get_sourcehostname():
if not CONFIG.get('SOURCEHOSTNAME'):
log(f"SOURCEHOSTNAME empty, retrieving from {CONFIG['SOURCEHOST']}...")
result = rssh(["hostname"])
CONFIG['SOURCEHOSTNAME'] = result.stdout.strip()
log(f"Detected SOURCEHOSTNAME: {CONFIG['SOURCEHOSTNAME']}")
def shutdown_now():
if CONFIG.get('SHUTDOWN', 'no').lower() == 'yes':
# Hier würde Python wait_replace() aufrufen, send_piggyback() etc.
log("Shutdown requested. Would execute now...")
else:
log("No shutdown requested.")
# === Weitere Funktionen nach Bash ===
# zfs_replace(), wait_replace(), write_zsync_config(), run_zsync(),
# run_remote_updates(), send_piggyback(), run_pbs_backup(), etc.
# === Main Execution ===
def main():
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--config", help="Path to config")
parser.add_argument("function", nargs='?', help="Run specific function")
args = parser.parse_args()
if args.config:
load_config(args.config)
if args.function:
func = globals().get(args.function)
if func:
func()
else:
log(f"Function {args.function} not found")
sys.exit(1)
else:
# Full backup run
log("Running full backup...")
# Full run calls all functions like in Bash
# wait(), set_dynamic_route(), write_zsync_config(), run_zsync(), etc.