feat: add tool catalog and installation endpoints with models for tool management
This commit is contained in:
@@ -11,6 +11,7 @@ from .domain import VmRecord
|
||||
from .errors import ValidationError
|
||||
from .guest_agent import DEFAULT_TIMEOUT_SECONDS, MAX_COMMAND_BYTES, MAX_TIMEOUT_SECONDS
|
||||
from .guest_exec import validate_exec
|
||||
from .tool_catalog import MAX_SELECTIONS, ToolSelection
|
||||
|
||||
|
||||
class HealthResponse(BaseModel):
|
||||
@@ -42,6 +43,19 @@ class PortRuleModel(BaseModel):
|
||||
protocol: Literal["TCP", "HTTP", "HTTPS"] = "TCP"
|
||||
|
||||
|
||||
class ToolSelectionModel(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
id: str = Field(strict=True, min_length=1, max_length=32)
|
||||
version: str | None = Field(default=None, strict=True, max_length=16,
|
||||
description="Required for Python: 3.11, 3.12, or 3.13. Omit for other tools.")
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_selection(self):
|
||||
ToolSelection(self.id, self.version)
|
||||
return self
|
||||
|
||||
|
||||
class VmCreateRequest(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
@@ -54,6 +68,8 @@ class VmCreateRequest(BaseModel):
|
||||
name: str | None = None
|
||||
ports: list[PortRuleModel] | None = None
|
||||
no_default_ports: bool = Field(default=False, strict=True)
|
||||
tools: list[ToolSelectionModel] = Field(default_factory=list, max_length=MAX_SELECTIONS,
|
||||
description="Optional guest tools to install asynchronously after boot")
|
||||
|
||||
|
||||
class VmResizeRequest(BaseModel):
|
||||
@@ -149,6 +165,78 @@ class VmAgentInstallResponse(BaseModel):
|
||||
restart_required: bool = True
|
||||
|
||||
|
||||
class ToolCatalogResponse(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
description: str
|
||||
version_label: str
|
||||
versions: list[str]
|
||||
source: str
|
||||
|
||||
|
||||
class ToolInstallRequest(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
tools: list[ToolSelectionModel] = Field(min_length=1, max_length=MAX_SELECTIONS)
|
||||
start_if_stopped: bool = Field(default=False, strict=True)
|
||||
restart: bool = Field(default=False, strict=True, description="Restart first to refresh the guest agent")
|
||||
request_id: str | None = Field(default=None, strict=True, max_length=80, pattern=r"^[A-Za-z0-9_-]{1,80}$",
|
||||
description="Optional idempotency key, retained with the most recent 10 jobs")
|
||||
|
||||
|
||||
class ToolInventoryResponse(BaseModel):
|
||||
key: str
|
||||
id: str
|
||||
version: str | None
|
||||
installed: bool
|
||||
detected_version: str | None
|
||||
error: str | None
|
||||
usage: str
|
||||
|
||||
|
||||
class ToolJobItemResponse(BaseModel):
|
||||
key: str
|
||||
id: str
|
||||
version: str | None
|
||||
status: Literal["queued", "installing", "installed", "already_installed", "failed", "interrupted", "skipped"]
|
||||
detected_version: str | None
|
||||
error: str | None
|
||||
output: str
|
||||
truncated: bool
|
||||
|
||||
|
||||
class ToolJobSummaryResponse(BaseModel):
|
||||
id: str
|
||||
status: Literal["queued", "starting", "waiting", "installing", "succeeded", "failed", "interrupted"]
|
||||
created_at: float
|
||||
completed_at: float | None
|
||||
|
||||
|
||||
class ToolJobResponse(ToolJobSummaryResponse):
|
||||
vm_id: str
|
||||
source: Literal["create", "user"]
|
||||
updated_at: float
|
||||
start_if_stopped: bool
|
||||
restart: bool
|
||||
request_id: str | None
|
||||
error: str | None
|
||||
outcome_unknown: bool
|
||||
items: list[ToolJobItemResponse]
|
||||
|
||||
|
||||
class VmToolsResponse(BaseModel):
|
||||
vm_id: str
|
||||
inventory: list[ToolInventoryResponse]
|
||||
checked_at: float | None
|
||||
agent_ready: bool
|
||||
guest_busy: bool
|
||||
supported: bool | None
|
||||
error: str | None
|
||||
stale: bool
|
||||
latest_job: ToolJobResponse | None
|
||||
jobs: list[ToolJobSummaryResponse]
|
||||
|
||||
|
||||
class DiagnosticResponse(BaseModel):
|
||||
name: str
|
||||
ok: bool
|
||||
|
||||
Reference in New Issue
Block a user