from datetime import datetime, timezone from typing import Optional from sqlmodel import Field, SQLModel def utcnow() -> datetime: return datetime.now(timezone.utc) class Server(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) name: str host: str port: int = 22 username: str = "root" auth_type: str = "password" # password | key password: Optional[str] = None # см. README: для продакшена — keyring key_path: Optional[str] = None sudo_password: Optional[str] = None # если None — берётся password tags: str = "" # через запятую note: str = "" # пользовательская заметка color: str = "blue" read_only: bool = False created_at: datetime = Field(default_factory=utcnow) class TaskRecord(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) server_id: Optional[int] = None kind: str # update/upgrade/reboot/install/docker/... title: str status: str = "pending" # pending/running/success/error/cancelled log: str = "" created_at: datetime = Field(default_factory=utcnow) finished_at: Optional[datetime] = None class MetricSnapshot(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) server_id: int cpu_percent: float = 0.0 mem_percent: float = 0.0 mem_used_mb: int = 0 mem_total_mb: int = 0 disk_percent: float = 0.0 load1: float = 0.0 net_rx_kbs: float = 0.0 net_tx_kbs: float = 0.0 ts: datetime = Field(default_factory=utcnow) class CronBackup(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) server_id: int user: str content: str created_at: datetime = Field(default_factory=utcnow) class Setting(SQLModel, table=True): key: str = Field(primary_key=True) value: str = "" class ScheduledTask(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) name: str cron: str # 5-полевое выражение action: str # apt_update/upgrade/dist_upgrade/shell/backup/playbook/report/cleanup_metrics target: str = "all" # "all" или тег params: str = "" # команда / пути бэкапа / имя плейбука enabled: bool = True last_run: Optional[datetime] = None last_status: str = "" class BackupRecord(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) server_id: int paths: str file: str = "" # локальный путь скачанного архива size: int = 0 status: str = "pending" # pending/success/error log: str = "" created_at: datetime = Field(default_factory=utcnow) class WebhookBinding(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) repo: str # full_name, напр. dimon/myapp server_id: int branch: str = "main" compose_path: str = "docker-compose.yml" env: str = "" enabled: bool = True