Archived
100 lines
3.7 KiB
Python
100 lines
3.7 KiB
Python
from datetime import datetime, timezone
|
|
from enum import Enum
|
|
|
|
from sqlalchemy import Boolean, DateTime, Enum as SqlEnum, ForeignKey, Integer, String, Text
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from .database import Base
|
|
|
|
|
|
class UserRole(str, Enum):
|
|
"""Роли пользователей панели."""
|
|
|
|
admin = "admin"
|
|
client = "client"
|
|
|
|
|
|
class GuestType(str, Enum):
|
|
"""Тип виртуализированной системы."""
|
|
|
|
vm = "vm"
|
|
lxc = "lxc"
|
|
|
|
|
|
class InstanceStatus(str, Enum):
|
|
"""Состояние инстанса в панели."""
|
|
|
|
creating = "creating"
|
|
running = "running"
|
|
stopped = "stopped"
|
|
error = "error"
|
|
deleting = "deleting"
|
|
deleted = "deleted"
|
|
|
|
|
|
class User(Base):
|
|
"""Пользователь панели с Argon2id-хешем пароля."""
|
|
|
|
__tablename__ = "users"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
|
email: Mapped[str] = mapped_column(String(320), unique=True, index=True)
|
|
password_hash: Mapped[str] = mapped_column(String(512))
|
|
role: Mapped[UserRole] = mapped_column(
|
|
SqlEnum(UserRole), default=UserRole.client, nullable=False
|
|
)
|
|
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
default=lambda: datetime.now(timezone.utc),
|
|
nullable=False,
|
|
)
|
|
instances: Mapped[list["Instance"]] = relationship(back_populates="owner")
|
|
|
|
|
|
class Template(Base):
|
|
"""Тарифный шаблон VM или LXC, доступный клиентам."""
|
|
|
|
__tablename__ = "templates"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
|
name: Mapped[str] = mapped_column(String(64), unique=True, index=True)
|
|
description: Mapped[str] = mapped_column(Text, default="")
|
|
guest_type: Mapped[GuestType] = mapped_column(SqlEnum(GuestType), nullable=False)
|
|
source_vmid: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
source_template: Mapped[str | None] = mapped_column(String(512), nullable=True)
|
|
cores: Mapped[int] = mapped_column(Integer, default=1, nullable=False)
|
|
memory_mb: Mapped[int] = mapped_column(Integer, default=1024, nullable=False)
|
|
disk_gb: Mapped[int] = mapped_column(Integer, default=10, nullable=False)
|
|
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
default=lambda: datetime.now(timezone.utc),
|
|
nullable=False,
|
|
)
|
|
instances: Mapped[list["Instance"]] = relationship(back_populates="template")
|
|
|
|
|
|
class Instance(Base):
|
|
"""Инстанс VM/LXC, принадлежащий пользователю."""
|
|
|
|
__tablename__ = "instances"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
|
name: Mapped[str] = mapped_column(String(63))
|
|
vmid: Mapped[int | None] = mapped_column(Integer, unique=True, nullable=True)
|
|
node: Mapped[str] = mapped_column(String(64))
|
|
guest_type: Mapped[GuestType] = mapped_column(SqlEnum(GuestType), nullable=False)
|
|
status: Mapped[InstanceStatus] = mapped_column(
|
|
SqlEnum(InstanceStatus), default=InstanceStatus.creating, nullable=False
|
|
)
|
|
owner_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True)
|
|
template_id: Mapped[int] = mapped_column(ForeignKey("templates.id"), index=True)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
default=lambda: datetime.now(timezone.utc),
|
|
nullable=False,
|
|
)
|
|
owner: Mapped[User] = relationship(back_populates="instances")
|
|
template: Mapped[Template] = relationship(back_populates="instances")
|