Files
nest/uvm/api_models.py
T
kstyagi b3b1b527e1 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.
2026-09-19 10:50:29 +05:30

145 lines
3.3 KiB
Python

"""Pydantic request and response models for the UVM HTTP API."""
from __future__ import annotations
from ipaddress import IPv4Address
from typing import Literal
from pydantic import BaseModel, ConfigDict, Field, SecretStr
from .domain import VmRecord
class HealthResponse(BaseModel):
status: str = "ok"
class InstallRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
force: bool = False
class InstallResponse(BaseModel):
firecracker: str
kernel: str
rootfs: str
class PortRuleModel(BaseModel):
"""A private guest TCP port; HTTP and HTTPS are descriptive labels only."""
model_config = ConfigDict(extra="forbid")
port: int = Field(strict=True, ge=1, le=65535)
protocol: Literal["TCP", "HTTP", "HTTPS"] = "TCP"
class VmCreateRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
cpu: float = Field(default=1, gt=0)
ram: str | int | float = "512"
guest_ip: IPv4Address | None = None
username: str = "root"
password: SecretStr = SecretStr("root")
name: str | None = None
ports: list[PortRuleModel] | None = None
no_default_ports: bool = Field(default=False, strict=True)
class VmResponse(BaseModel):
id: str
name: str | None
cpu: float
ram_mib: int
guest_ip: str
gateway: str
mac: str
username: str
status: str
observed_status: str
ports: list[PortRuleModel] | None
policy_status: str
operation: str | None
pid: int | None
created_at: int
updated_at: int
last_error: str | None
class DestroyResponse(BaseModel):
id: str
status: str = "terminated"
class PortUpdateRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
mode: Literal["set", "open", "close"] = "set"
ports: list[PortRuleModel] = Field(default_factory=list)
class PortSyncResponse(BaseModel):
id: str
policy_status: str
status: str
class VmLogResponse(BaseModel):
content: str
truncated: bool
class DiagnosticResponse(BaseModel):
name: str
ok: bool
message: str
class VmBulkActionRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
action: Literal["start", "stop", "restart", "delete", "ports-sync"]
identifiers: list[str] = Field(default_factory=list)
all_vms: bool = Field(default=False, strict=True)
timeout: float | None = None
class VmActionResultResponse(BaseModel):
id: str
action: str
outcome: str
error: str | None = None
def vm_response(
vm: VmRecord,
*,
observed_status: str | None = None,
policy_status: str = "unknown",
) -> VmResponse:
return VmResponse(
id=vm.id,
name=vm.name,
cpu=vm.cpu,
ram_mib=vm.ram_mib,
guest_ip=vm.guest_ip,
gateway=vm.gateway,
mac=vm.mac,
username=vm.username,
status=vm.status,
observed_status=observed_status if observed_status is not None else vm.status,
ports=(
[PortRuleModel(port=rule.port, protocol=rule.protocol) for rule in vm.ports]
if vm.ports is not None
else None
),
policy_status=policy_status,
operation=vm.operation,
pid=vm.pid,
created_at=vm.created_at,
updated_at=vm.updated_at,
last_error=vm.last_error,
)