(release) Add purged snapshot audit overview
Record snapshot purge history whenever retention or incomplete cleanup removes snapshot directories and SQL records. Store the purge reason, original kind, path, action source, and triggering operator so manual, scheduled, CLI, and incomplete cleanup actions remain auditable after the original snapshot record is deleted. Add a staff-only Purged Snapshots page with host/action filters and register the audit model in Django admin. Refs #16 Refs #8
This commit is contained in:
@@ -33,7 +33,7 @@ from .forms import (
|
||||
SshCredentialForm,
|
||||
)
|
||||
from .host_ops import ensure_host_directories
|
||||
from .models import BackupRun, GlobalConfig, HostConfig, ScheduleConfig, SnapshotRecord, SshCredential
|
||||
from .models import BackupRun, GlobalConfig, HostConfig, PurgedSnapshot, ScheduleConfig, SnapshotRecord, SshCredential
|
||||
from .preflight import collect_backup_gate, effective_host_config_preview, run_remote_preflight
|
||||
from .retention import run_incomplete_cleanup, run_sql_retention_apply, run_sql_retention_plan
|
||||
from .self_check import collect_self_checks, summarize_self_checks
|
||||
@@ -145,6 +145,27 @@ def logs(request):
|
||||
return render(request, "pobsync_backend/logs.html", context)
|
||||
|
||||
|
||||
@staff_member_required
|
||||
def purged_snapshots(request):
|
||||
host = request.GET.get("host", "").strip()
|
||||
action = request.GET.get("action", "").strip()
|
||||
purged = PurgedSnapshot.objects.select_related("host").order_by("-purged_at", "host_name", "dirname")
|
||||
if host:
|
||||
purged = purged.filter(host_name=host)
|
||||
if action:
|
||||
purged = purged.filter(action=action)
|
||||
|
||||
context = {
|
||||
"purged_snapshots": purged[:200],
|
||||
"hosts": HostConfig.objects.order_by("host"),
|
||||
"actions": PurgedSnapshot.Action.choices,
|
||||
"selected_host": host,
|
||||
"selected_action": action,
|
||||
"total_count": purged.count(),
|
||||
}
|
||||
return render(request, "pobsync_backend/purged_snapshots.html", context)
|
||||
|
||||
|
||||
@staff_member_required
|
||||
def ssh_credentials(request):
|
||||
context = {
|
||||
@@ -693,6 +714,8 @@ def apply_host_retention(request, host: str):
|
||||
protect_bases=protect_bases,
|
||||
yes=True,
|
||||
max_delete=form.cleaned_data["max_delete"],
|
||||
action=PurgedSnapshot.Action.MANUAL,
|
||||
triggered_by=request.user.get_username(),
|
||||
)
|
||||
except PobsyncError as exc:
|
||||
messages.error(request, str(exc))
|
||||
@@ -733,6 +756,7 @@ def cleanup_host_incomplete_snapshots(request, host: str):
|
||||
host=host_config.host,
|
||||
yes=True,
|
||||
max_delete=form.cleaned_data["max_delete"],
|
||||
triggered_by=request.user.get_username(),
|
||||
)
|
||||
except PobsyncError as exc:
|
||||
messages.error(request, str(exc))
|
||||
|
||||
Reference in New Issue
Block a user