fix(templates): автоматически сохранять короткое имя LXC как корректный Proxmox volid
This commit is contained in:
@@ -12,6 +12,47 @@ logger = logging.getLogger(__name__)
|
|||||||
router = APIRouter(prefix="/templates", tags=["templates"])
|
router = APIRouter(prefix="/templates", tags=["templates"])
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_lxc_source(value: str | None) -> str | None:
|
||||||
|
"""Приводит источник LXC к корректному Proxmox volid.
|
||||||
|
|
||||||
|
Принимает как полный volid:
|
||||||
|
``local:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst``
|
||||||
|
|
||||||
|
так и короткое имя:
|
||||||
|
``debian-13-standard_13.6-1_amd64``.
|
||||||
|
"""
|
||||||
|
if not value:
|
||||||
|
return None
|
||||||
|
|
||||||
|
source = value.strip()
|
||||||
|
if not source:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Если уже передан полный volid, оставляем его без изменений.
|
||||||
|
if ":" in source:
|
||||||
|
return source
|
||||||
|
|
||||||
|
# Сначала пытаемся найти точный volid среди шаблонов Proxmox.
|
||||||
|
# Это позволяет корректно обработать .tar.zst, .tar.gz и .tar.xz.
|
||||||
|
try:
|
||||||
|
for item in pve.list_lxc_templates():
|
||||||
|
if item.get("name") == source:
|
||||||
|
return item["volid"]
|
||||||
|
volid_name = item.get("volid", "").split("/")[-1]
|
||||||
|
if volid_name:
|
||||||
|
for extension in (".tar.zst", ".tar.gz", ".tar.xz"):
|
||||||
|
if volid_name.removesuffix(extension) == source:
|
||||||
|
return item["volid"]
|
||||||
|
except Exception as exc:
|
||||||
|
logger.warning("Не удалось сопоставить LXC-шаблон с Proxmox: %s", exc)
|
||||||
|
|
||||||
|
# Fallback для локального storage: короткое имя превращаем в volid.
|
||||||
|
for extension in (".tar.zst", ".tar.gz", ".tar.xz"):
|
||||||
|
if source.endswith(extension):
|
||||||
|
return f"local:vztmpl/{source}"
|
||||||
|
return f"local:vztmpl/{source}.tar.zst"
|
||||||
|
|
||||||
|
|
||||||
@router.get("", response_model=List[schemas.TemplateOut])
|
@router.get("", response_model=List[schemas.TemplateOut])
|
||||||
def list_templates(db: Session = Depends(get_db), _=Depends(get_current_user)):
|
def list_templates(db: Session = Depends(get_db), _=Depends(get_current_user)):
|
||||||
"""Возвращает активные шаблоны, сохранённые в панели."""
|
"""Возвращает активные шаблоны, сохранённые в панели."""
|
||||||
@@ -24,8 +65,21 @@ def create_template(
|
|||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
_=Depends(require_admin),
|
_=Depends(require_admin),
|
||||||
):
|
):
|
||||||
"""Добавляет шаблон в каталог панели."""
|
"""Добавляет шаблон в каталог панели.
|
||||||
tpl = models.Template(**payload.model_dump())
|
|
||||||
|
Для LXC автоматически нормализует короткое имя архива в Proxmox volid.
|
||||||
|
"""
|
||||||
|
data = payload.model_dump()
|
||||||
|
if data.get("guest_type") == models.GuestType.lxc:
|
||||||
|
data["source_vmid"] = None
|
||||||
|
data["source_template"] = _normalize_lxc_source(data.get("source_template"))
|
||||||
|
if not data["source_template"]:
|
||||||
|
from fastapi import HTTPException
|
||||||
|
raise HTTPException(status_code=400, detail="Для LXC нужно указать архивный шаблон")
|
||||||
|
else:
|
||||||
|
data["source_template"] = None
|
||||||
|
|
||||||
|
tpl = models.Template(**data)
|
||||||
db.add(tpl)
|
db.add(tpl)
|
||||||
db.commit()
|
db.commit()
|
||||||
db.refresh(tpl)
|
db.refresh(tpl)
|
||||||
@@ -34,10 +88,7 @@ def create_template(
|
|||||||
|
|
||||||
@router.get("/from-proxmox")
|
@router.get("/from-proxmox")
|
||||||
def list_proxmox_templates(_=Depends(require_admin)):
|
def list_proxmox_templates(_=Depends(require_admin)):
|
||||||
"""Возвращает VM-шаблоны и архивные LXC-шаблоны с Proxmox.
|
"""Возвращает VM-шаблоны и архивные LXC-шаблоны с Proxmox."""
|
||||||
|
|
||||||
Готовые LXC-контейнеры по VMID намеренно не показываются.
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
vm_templates = pve.list_vm_templates()
|
vm_templates = pve.list_vm_templates()
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|||||||
Reference in New Issue
Block a user