feat: Borg-Diagnose und manuellen Backup-Start ergaenzen
This commit is contained in:
parent
3fcbc8268f
commit
c019d2dcec
1 changed files with 55 additions and 0 deletions
55
app.py
55
app.py
|
|
@ -546,6 +546,61 @@ async def backup_status(_=Depends(_verify)):
|
||||||
return await _collect_backup_status()
|
return await _collect_backup_status()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/backup/diagnose/{hostname}")
|
||||||
|
async def backup_diagnose(hostname: str, _=Depends(_verify)):
|
||||||
|
"""Safe Borgmatic timer/service diagnostics without exposing backup secrets."""
|
||||||
|
host = await asyncio.to_thread(_find_inventory_host, hostname)
|
||||||
|
if not host or host["name"].startswith("node"):
|
||||||
|
return JSONResponse({"error": "inventory host not found"}, status_code=404)
|
||||||
|
command = """echo __TIMER_ENABLED__
|
||||||
|
sudo -n systemctl is-enabled borg-backup.timer 2>&1 || true
|
||||||
|
echo __TIMER_ACTIVE__
|
||||||
|
sudo -n systemctl is-active borg-backup.timer 2>&1 || true
|
||||||
|
echo __TIMER_SCHEDULE__
|
||||||
|
sudo -n systemctl list-timers borg-backup.timer --all --no-pager 2>&1 || true
|
||||||
|
echo __SERVICE_STATE__
|
||||||
|
sudo -n systemctl show borg-backup.service -p ActiveState -p SubState -p Result -p ExecMainStatus --no-pager 2>&1 || true
|
||||||
|
echo __RECENT_LOGS__
|
||||||
|
sudo -n journalctl -u borg-backup.service --since '2 days ago' -n 120 --no-pager 2>&1 || true
|
||||||
|
echo __LATEST_ARCHIVE__
|
||||||
|
timeout 50s sudo -n borgmatic list --last 1 --json 2>&1 || true
|
||||||
|
"""
|
||||||
|
rc, out, err = await asyncio.to_thread(
|
||||||
|
_ssh, f'{host["user"]}@{host["ip"]}', command, 75
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
"hostname": host["name"], "ip": host["ip"], "user": host["user"],
|
||||||
|
"rc": rc, "output": out[-30000:], "stderr": err[-2000:],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/backup/run/{hostname}")
|
||||||
|
async def backup_run(hostname: str, _=Depends(_verify)):
|
||||||
|
"""Start one inventory host Borgmatic service asynchronously."""
|
||||||
|
host = await asyncio.to_thread(_find_inventory_host, hostname)
|
||||||
|
if not host or host["name"].startswith("node"):
|
||||||
|
return JSONResponse({"error": "inventory host not found"}, status_code=404)
|
||||||
|
command = (
|
||||||
|
"sudo -n systemctl reset-failed borg-backup.service 2>/dev/null || true; "
|
||||||
|
"sudo -n systemctl start --no-block borg-backup.service; sleep 2; "
|
||||||
|
"sudo -n systemctl show borg-backup.service -p ActiveState -p SubState -p Result --no-pager"
|
||||||
|
)
|
||||||
|
rc, out, err = await asyncio.to_thread(
|
||||||
|
_ssh, f'{host["user"]}@{host["ip"]}', command, 20
|
||||||
|
)
|
||||||
|
_audit(f"/backup/run/{hostname}", "POST", 202 if rc == 0 else 500, f"rc={rc}")
|
||||||
|
if rc != 0:
|
||||||
|
return JSONResponse(
|
||||||
|
{"error": "backup start failed", "hostname": hostname,
|
||||||
|
"stdout": out[-2000:], "stderr": err[-2000:]},
|
||||||
|
status_code=500,
|
||||||
|
)
|
||||||
|
return JSONResponse(
|
||||||
|
{"status": "started", "hostname": hostname, "detail": out.strip()},
|
||||||
|
status_code=202,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def _collect_disk_usage(concurrency: int = 10) -> dict:
|
async def _collect_disk_usage(concurrency: int = 10) -> dict:
|
||||||
semaphore = asyncio.Semaphore(concurrency)
|
semaphore = asyncio.Semaphore(concurrency)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue