From d02a86f8f1d6498f858207ceb69a274605a09f94 Mon Sep 17 00:00:00 2001 From: host Date: Sun, 9 Aug 2026 18:40:44 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20LXC=20=D0=BE=D0=B3=D1=80=D0=B0=D0=BD=D0=B8=D1=87=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=B0=D1=80=D1=85=D0=B8=D0=B2=D0=BD=D1=8B=D0=BC?= =?UTF-8?q?=D0=B8=20=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/routers/instances.py | 59 +++++++++----------------------- 1 file changed, 17 insertions(+), 42 deletions(-) diff --git a/backend/app/routers/instances.py b/backend/app/routers/instances.py index 56f2ed4..11d7584 100644 --- a/backend/app/routers/instances.py +++ b/backend/app/routers/instances.py @@ -65,29 +65,19 @@ def _provision(instance_id: int, template_id: int, node: str) -> None: pve.configure_cloud_init(instance.vmid, instance.ciuser, instance.root_password, node) pve.guest_action("vm", instance.vmid, "start", node) else: - password = instance.root_password or pve.gen_password() - if template.source_vmid: - pve.clone_lxc( - source_vmid=template.source_vmid, - new_vmid=instance.vmid, - name=clean_name, - cores=template.cores, - memory_mb=template.memory_mb, - password=password, - node=node, - ) - elif template.source_template: - password = pve.create_lxc( - new_vmid=instance.vmid, - name=clean_name, - template_volid=template.source_template, - cores=template.cores, - memory_mb=template.memory_mb, - disk_gb=template.disk_gb, - node=node, - ) - else: - raise ValueError("У LXC-шаблона не указан source_vmid или source_template") + # LXC создаётся только из архивного шаблона vzdump. + # Готовые LXC-контейнеры по VMID намеренно не используются. + if not template.source_template: + raise ValueError("У LXC-шаблона не указан source_template") + password = pve.create_lxc( + new_vmid=instance.vmid, + name=clean_name, + template_volid=template.source_template, + cores=template.cores, + memory_mb=template.memory_mb, + disk_gb=template.disk_gb, + node=node, + ) instance.root_password = password pve.guest_action("lxc", instance.vmid, "start", node) @@ -109,13 +99,7 @@ def create_instance( db: Session = Depends(get_db), user: models.User = Depends(get_current_user), ): - """Регистрирует один инстанс и запускает его создание в фоне. - - Блокировка строки пользователя и проверка статуса creating не позволяют - повторному клику создать несколько VPS для одного пользователя. - """ - # Блокируем пользователя на время резервирования VMID и записи инстанса. - # Это защищает от двух почти одновременных POST-запросов из браузера. + """Регистрирует один инстанс и запускает его создание в фоне.""" db.query(models.User).filter(models.User.id == user.id).with_for_update().one() pending = ( db.query(models.Instance) @@ -126,10 +110,7 @@ def create_instance( .first() ) if pending: - raise HTTPException( - status_code=409, - detail="Предыдущий VPS ещё создаётся. Дождитесь завершения операции.", - ) + raise HTTPException(status_code=409, detail="Предыдущий VPS ещё создаётся. Дождитесь завершения операции.") template = ( db.query(models.Template) @@ -147,18 +128,14 @@ def create_instance( active = ( db.query(models.Instance) - .filter( - models.Instance.vmid == vmid, - models.Instance.status != models.InstanceStatus.deleted, - ) + .filter(models.Instance.vmid == vmid, models.Instance.status != models.InstanceStatus.deleted) .first() ) if active: raise HTTPException(status_code=409, detail=f"VMID {vmid} уже используется в панели") - clean_name = _sanitize_name(payload.name) instance = models.Instance( - name=clean_name, + name=_sanitize_name(payload.name), vmid=vmid, node=settings.pve_node, guest_type=template.guest_type, @@ -258,7 +235,6 @@ def delete_instance(instance_id: int, db: Session = Depends(get_db), user: model _ensure_owner(instance, user) if instance.status == models.InstanceStatus.deleting: raise HTTPException(status_code=409, detail="Инстанс уже удаляется") - instance.status = models.InstanceStatus.deleting db.commit() try: @@ -268,7 +244,6 @@ def delete_instance(instance_id: int, db: Session = Depends(get_db), user: model instance.status = models.InstanceStatus.error db.commit() raise HTTPException(status_code=502, detail=f"Ошибка удаления: {exc}") - instance.status = models.InstanceStatus.deleted db.commit() return {"ok": True}