From ae3997dbbc92e956f2fbd0c42390cb83e3e6a830 Mon Sep 17 00:00:00 2001 From: host Date: Sun, 9 Aug 2026 14:31:01 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D1=81=D1=85=D0=B5=D0=BC=D1=8B=20=D1=88=D0=B0?= =?UTF-8?q?=D0=B1=D0=BB=D0=BE=D0=BD=D0=BE=D0=B2=20=D0=B8=20=D0=B8=D0=BD?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BD=D1=81=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/schemas.py | 57 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/backend/app/schemas.py b/backend/app/schemas.py index ccb6e45..baa6a68 100644 --- a/backend/app/schemas.py +++ b/backend/app/schemas.py @@ -1,8 +1,8 @@ from datetime import datetime -from pydantic import BaseModel, ConfigDict, EmailStr, Field +from pydantic import BaseModel, ConfigDict, EmailStr, Field, model_validator -from .models import UserRole +from .models import GuestType, InstanceStatus, UserRole class UserCreate(BaseModel): @@ -29,3 +29,56 @@ class TokenOut(BaseModel): access_token: str token_type: str = "bearer" + + +class TemplateCreate(BaseModel): + """Данные для создания шаблона администратором.""" + + name: str = Field(min_length=1, max_length=64, pattern=r"^[a-zA-Z0-9][a-zA-Z0-9-]*$") + description: str = Field(default="", max_length=2000) + guest_type: GuestType + source_vmid: int | None = Field(default=None, gt=0) + source_template: str | None = Field(default=None, min_length=1, max_length=512) + cores: int = Field(default=1, ge=1, le=64) + memory_mb: int = Field(default=1024, ge=128, le=262144) + disk_gb: int = Field(default=10, ge=1, le=4096) + + @model_validator(mode="after") + def validate_source(self): + """Проверяет источник в зависимости от типа гостя.""" + if self.guest_type == GuestType.vm and self.source_vmid is None: + raise ValueError("Для VM требуется source_vmid") + if self.guest_type == GuestType.lxc and not self.source_template: + raise ValueError("Для LXC требуется source_template") + return self + + +class TemplateOut(BaseModel): + """Публичное представление активного шаблона.""" + + model_config = ConfigDict(from_attributes=True) + + id: int + name: str + description: str + guest_type: GuestType + cores: int + memory_mb: int + disk_gb: int + is_active: bool + + +class InstanceOut(BaseModel): + """Инстанс без credentials и внутренних секретов.""" + + model_config = ConfigDict(from_attributes=True) + + id: int + name: str + vmid: int | None + node: str + guest_type: GuestType + status: InstanceStatus + owner_id: int + template_id: int + created_at: datetime