(feature) improve snapshot discovery visibility in Django

Add a discovery preflight that reports the configured backup root, host
root, and snapshot directory counts before importing anything.

Show discovery status on host detail pages so missing mounts or mismatched
host directories are visible from the UI.

Warn clearly when discovery scans zero snapshots, including whether the
host backup directory is missing or simply empty.
This commit is contained in:
2026-05-19 13:21:31 +02:00
parent 573177e118
commit 1d90454109
7 changed files with 133 additions and 7 deletions

View File

@@ -12,6 +12,7 @@ from pobsync.util import write_yaml_atomic
from pobsync_backend.models import GlobalConfig, HostConfig, SnapshotRecord
from pobsync_backend.snapshot_discovery import (
discover_snapshots,
inspect_snapshot_discovery,
parse_snapshot_datetime,
resolve_base_links,
upsert_snapshot_record,
@@ -63,6 +64,30 @@ class SnapshotDiscoveryTests(TestCase):
self.assertEqual(record.kind, "scheduled")
self.assertEqual(record.started_at, datetime(2026, 5, 19, 2, 15, tzinfo=timezone.utc))
def test_inspect_snapshot_discovery_reports_missing_global_config(self) -> None:
host = HostConfig.objects.create(host="web-01", address="web-01.example.test")
result = inspect_snapshot_discovery(host=host)
self.assertFalse(result["ok"])
self.assertEqual(result["reason"], "missing_global_config")
self.assertEqual(result["total_candidates"], 0)
def test_inspect_snapshot_discovery_counts_snapshot_directories(self) -> None:
with TemporaryDirectory() as tmp:
backup_root = Path(tmp) / "backups"
GlobalConfig.objects.create(name="default", backup_root=str(backup_root))
host = HostConfig.objects.create(host="web-01", address="web-01.example.test")
(backup_root / host.host / "scheduled" / "20260519-021500Z__ABCDEFGH").mkdir(parents=True)
(backup_root / host.host / "manual" / "20260519-031500Z__MANUAL01").mkdir(parents=True)
result = inspect_snapshot_discovery(host=host)
self.assertTrue(result["ok"])
self.assertEqual(result["reason"], "ready")
self.assertEqual(result["total_candidates"], 2)
self.assertEqual(result["kind_counts"], {"scheduled": 1, "manual": 1, "incomplete": 0})
def test_discovery_links_snapshot_to_base_record(self) -> None:
with TemporaryDirectory() as tmp:
backup_root = Path(tmp) / "backups"