(feature) Add backup trend forecasting to the Django UI
Extend derived backup statistics with average daily new data and an estimated days-until-full forecast based on recent successful real runs. Show the new forecast metrics on the dashboard and add compact per-run trend bars on the host detail page so new data and matched link-dest data are easier to compare at a glance. Keep the implementation migration-free by deriving everything from the existing BackupRun result stats payload.
This commit is contained in:
@@ -85,6 +85,8 @@ class ViewTests(TestCase):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Backup Root Used")
|
||||
self.assertContains(response, "Runs Until Full")
|
||||
self.assertContains(response, "Avg Daily New")
|
||||
self.assertContains(response, "Days Until Full")
|
||||
self.assertContains(response, "10")
|
||||
self.assertContains(response, f"Run {run.id}")
|
||||
self.assertContains(response, "1000")
|
||||
@@ -582,16 +584,38 @@ class ViewTests(TestCase):
|
||||
},
|
||||
},
|
||||
)
|
||||
BackupRun.objects.create(
|
||||
host=host,
|
||||
status=BackupRun.Status.SUCCESS,
|
||||
snapshot=snapshot,
|
||||
started_at=datetime(2026, 5, 18, 2, 15, tzinfo=timezone.utc),
|
||||
result={
|
||||
"ok": True,
|
||||
"dry_run": False,
|
||||
"stats": {
|
||||
"duration_seconds": 35,
|
||||
"rsync": {
|
||||
"files_total": 150,
|
||||
"literal_data_bytes": 1024,
|
||||
"matched_data_bytes": 4096,
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
response = self.client.get(reverse("host_detail", args=[host.host]))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Backup Trends")
|
||||
self.assertContains(response, "Avg New Data")
|
||||
self.assertContains(response, "Avg Daily New")
|
||||
self.assertContains(response, "45s")
|
||||
self.assertContains(response, "250")
|
||||
self.assertContains(response, "2.0")
|
||||
self.assertContains(response, "KB")
|
||||
self.assertContains(response, "Run data trend")
|
||||
self.assertContains(response, "width: 100%")
|
||||
self.assertContains(response, "width: 50%")
|
||||
|
||||
def test_prepare_host_directories_action_creates_missing_directories(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
|
||||
Reference in New Issue
Block a user