feat: initial orchestrator service with FastAPI backend and premium GUI
- FastAPI backend with full Proxmox VE API integration - ISO builder using proxmox-auto-install-assistant - Premium dark-mode SPA frontend with glassmorphism design - VM lifecycle management (create, start, stop, destroy) - Build pipeline tracking with real-time logs - Deployment automation for custom auto-installer ISOs - Production deployment script (setup.sh + systemd) - Comprehensive README with API documentation
This commit is contained in:
+189
@@ -0,0 +1,189 @@
|
||||
"""
|
||||
Sovereign Orchestrator - Pydantic Models
|
||||
|
||||
Data models for API request/response payloads and internal state.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
from enum import Enum
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Enums
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class BuildState(str, Enum):
|
||||
"""Lifecycle states for an ISO build job."""
|
||||
PENDING = "pending"
|
||||
BUILDING = "building"
|
||||
UPLOADING = "uploading"
|
||||
COMPLETED = "completed"
|
||||
FAILED = "failed"
|
||||
|
||||
|
||||
class NetworkSource(str, Enum):
|
||||
"""Proxmox installer network source options."""
|
||||
FROM_DHCP = "from-dhcp"
|
||||
FROM_ANSWER = "from-answer"
|
||||
|
||||
|
||||
class Filesystem(str, Enum):
|
||||
"""Supported root filesystems."""
|
||||
EXT4 = "ext4"
|
||||
XFS = "xfs"
|
||||
ZFS = "zfs"
|
||||
BTRFS = "btrfs"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Request models
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class ISOConfig(BaseModel):
|
||||
"""Configuration payload for generating a custom auto-install ISO."""
|
||||
|
||||
fqdn: str = Field(
|
||||
..., description="Fully qualified domain name for the new host",
|
||||
examples=["pve-test.internal.718it.biz"],
|
||||
)
|
||||
keyboard: str = Field(default="en-us", description="Keyboard layout")
|
||||
country: str = Field(default="us", description="Country code")
|
||||
timezone: str = Field(
|
||||
default="America/New_York", description="Timezone string"
|
||||
)
|
||||
mailto: str = Field(
|
||||
default="wmantly@gmail.com", description="Admin email address"
|
||||
)
|
||||
root_password: str = Field(
|
||||
..., description="Root password for the installed system"
|
||||
)
|
||||
root_ssh_keys: list[str] = Field(
|
||||
default_factory=list,
|
||||
description="SSH public keys to authorize for root",
|
||||
)
|
||||
network_source: NetworkSource = Field(
|
||||
default=NetworkSource.FROM_DHCP,
|
||||
description="Network configuration source",
|
||||
)
|
||||
filesystem: Filesystem = Field(
|
||||
default=Filesystem.EXT4, description="Root filesystem type"
|
||||
)
|
||||
disk_list: list[str] = Field(
|
||||
default_factory=lambda: ["sda"],
|
||||
description="Disks to use for installation",
|
||||
)
|
||||
reboot_on_error: bool = Field(
|
||||
default=False, description="Reboot automatically on install error"
|
||||
)
|
||||
|
||||
|
||||
class DeployConfig(BaseModel):
|
||||
"""Configuration for deploying a VM with the custom ISO."""
|
||||
|
||||
vmid: int = Field(default=900, description="VM ID to create")
|
||||
node: str = Field(default="dl380-0", description="Proxmox node name")
|
||||
cores: int = Field(default=4, ge=1, le=128, description="CPU cores")
|
||||
memory: int = Field(
|
||||
default=8192, ge=512, description="Memory in MiB"
|
||||
)
|
||||
disk_size: str = Field(
|
||||
default="64G", description="Root disk size (e.g. 64G)"
|
||||
)
|
||||
build_id: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Build ID whose ISO to use. Defaults to latest.",
|
||||
)
|
||||
storage: str = Field(
|
||||
default="local-lvm", description="Proxmox storage for the VM disk"
|
||||
)
|
||||
iso_storage: str = Field(
|
||||
default="local", description="Proxmox storage containing ISOs"
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Internal / response models
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class BuildStatus(BaseModel):
|
||||
"""Tracks the state of an ISO build job."""
|
||||
|
||||
id: str = Field(default_factory=lambda: uuid.uuid4().hex[:12])
|
||||
state: BuildState = BuildState.PENDING
|
||||
iso_config: Optional[ISOConfig] = None
|
||||
iso_filename: Optional[str] = None
|
||||
logs: list[str] = Field(default_factory=list)
|
||||
created_at: datetime = Field(
|
||||
default_factory=lambda: datetime.now(timezone.utc)
|
||||
)
|
||||
updated_at: datetime = Field(
|
||||
default_factory=lambda: datetime.now(timezone.utc)
|
||||
)
|
||||
error: Optional[str] = None
|
||||
|
||||
def log(self, message: str) -> None:
|
||||
"""Append a timestamped log line."""
|
||||
ts = datetime.now(timezone.utc).isoformat()
|
||||
self.logs.append(f"[{ts}] {message}")
|
||||
self.updated_at = datetime.now(timezone.utc)
|
||||
|
||||
|
||||
class VMStatus(BaseModel):
|
||||
"""Proxmox VM status snapshot."""
|
||||
|
||||
vmid: int
|
||||
name: Optional[str] = None
|
||||
status: str
|
||||
node: str
|
||||
cpus: Optional[int] = None
|
||||
maxmem: Optional[int] = None
|
||||
maxdisk: Optional[int] = None
|
||||
uptime: Optional[int] = None
|
||||
pid: Optional[int] = None
|
||||
|
||||
|
||||
class NodeInfo(BaseModel):
|
||||
"""Proxmox node summary."""
|
||||
|
||||
node: str
|
||||
status: str
|
||||
cpu: Optional[float] = None
|
||||
maxcpu: Optional[int] = None
|
||||
mem: Optional[int] = None
|
||||
maxmem: Optional[int] = None
|
||||
uptime: Optional[int] = None
|
||||
|
||||
|
||||
class ISOInfo(BaseModel):
|
||||
"""ISO file metadata."""
|
||||
|
||||
volid: str
|
||||
filename: str
|
||||
size: Optional[int] = None
|
||||
|
||||
|
||||
class SystemStatus(BaseModel):
|
||||
"""Aggregate system status returned by /api/status."""
|
||||
|
||||
nodes: list[NodeInfo] = Field(default_factory=list)
|
||||
test_vm: Optional[VMStatus] = None
|
||||
available_isos: list[ISOInfo] = Field(default_factory=list)
|
||||
active_builds: list[BuildStatus] = Field(default_factory=list)
|
||||
proxmox_connected: bool = False
|
||||
error: Optional[str] = None
|
||||
|
||||
|
||||
class DeployResult(BaseModel):
|
||||
"""Response from a deploy operation."""
|
||||
|
||||
vmid: int
|
||||
node: str
|
||||
status: str
|
||||
message: str
|
||||
task_id: Optional[str] = None
|
||||
Reference in New Issue
Block a user