feat: Implement UVM Dashboard with frontend and backend integration

- Added dashboard.js for frontend functionality, including VM management and system health monitoring.
- Created dashboard route to serve the dashboard HTML.
- Introduced diagnostics route for token-protected host diagnostics.
- Enhanced VMs router with bulk actions, VM log retrieval, and port management.
- Updated lifecycle service to read VM log tails with truncation handling.
- Integrated static file serving for dashboard assets in the FastAPI server.
- Redirect root URL to the dashboard for improved user experience.
This commit is contained in:
2026-09-19 10:50:29 +05:30
parent 3d7af4adb8
commit b3b1b527e1
17 changed files with 2285 additions and 69 deletions
+17
View File
@@ -600,6 +600,23 @@ class LifecycleInspectionTests(LifecycleTestCase):
self.assertFalse(settings.base.exists())
self.assertEqual(self.host.events, [])
def test_read_log_tail_is_bounded_and_marks_an_oversized_line(self) -> None:
vm = self.create_vm(name="log-reader")
path = Path(vm.log)
path.write_bytes(b"old\n" * 100_000 + b"last\n" * 2)
tail = self.service.read_log_tail(vm.id, tail=2)
self.assertEqual(tail.content, "last\n" * 2)
self.assertFalse(tail.truncated)
with self.assertRaisesRegex(ValidationError, "non-negative"):
self.service.read_log_tail(vm.id, tail=-1)
path.write_bytes(b"x" * 300_000)
truncated = self.service.read_log_tail(vm.id, tail=1)
self.assertEqual(len(truncated.content), 262_144)
self.assertTrue(truncated.truncated)
def test_diagnostics_collects_failures_without_host_commands_or_lifecycle_effects(self) -> None:
self.check_kvm.side_effect = UvmError("KVM unavailable")
self.host.failures["firewall.check_available", None] = UvmError("nft unavailable")