From 7fff059952fd2c43538efe2429f039a30f6c34b1 Mon Sep 17 00:00:00 2001 From: host Date: Sun, 9 Aug 2026 20:53:04 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D1=82=D1=8C=20cl?= =?UTF-8?q?one=5Flxc=20(=D0=BF=D1=80=D0=B5=D0=B4=D0=BB=D0=BE=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=20VMID),=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D0=BF=D0=B8=D1=81=D0=B0=D1=82=D1=8C=20create=5Flxc=20?= =?UTF-8?q?=D0=BD=D0=B0=204=20=D1=8F=D0=B2=D0=BD=D1=8B=D1=85=20=D1=88?= =?UTF-8?q?=D0=B0=D0=B3=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/proxmox_client.py | 60 ++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/backend/app/proxmox_client.py b/backend/app/proxmox_client.py index a9b87f7..42b4b50 100644 --- a/backend/app/proxmox_client.py +++ b/backend/app/proxmox_client.py @@ -47,27 +47,6 @@ def clone_vm(source_vmid: int, new_vmid: int, name: str, node: str = None, stora _wait_task(px, node, upid) -def clone_lxc(source_vmid: int, new_vmid: int, name: str, cores: int, memory_mb: int, password: str, node: str = None) -> str: - """Клонирует LXC-шаблон по VMID и задаёт ресурсы и пароль.""" - node = node or settings.pve_node - px = _client() - upid = px.nodes(node).lxc(source_vmid).clone.post( - newid=new_vmid, - hostname=name, - full=1, - ) - _wait_task(px, node, upid) - px.nodes(node).lxc(new_vmid).config.put( - hostname=name, - cores=cores, - memory=memory_mb, - swap=memory_mb, - ) - # У LXC отдельный endpoint для смены пароля root. - px.nodes(node).lxc(new_vmid).passwd.post(password=password) - return password - - def resize_vm(vmid: int, cores: int, memory_mb: int, node: str = None) -> None: """Изменяет количество vCPU и RAM у VM.""" node = node or settings.pve_node @@ -84,10 +63,23 @@ def create_lxc( storage: str = "local-lvm", node: str = None, ) -> str: - """Создаёт LXC из архива vzdump-шаблона.""" + """Создаёт LXC из архивного шаблона и запускает его. + + Шаги (каждый — отдельный запрос к Proxmox API): + 1. Создаёт LXC через ``ostemplate`` (без запуска). + 2. Задаёт новый root-пароль через ``/passwd``. + 3. Создаёт rootfs указанного размера через ``/resize``. + 4. Запускает контейнер через ``/status/start``. + + LXC создаётся ТОЛЬКО из архивного шаблона (vztmpl на storage). + Клонирование существующего LXC по VMID не поддерживается. + """ node = node or settings.pve_node px = _client() password = gen_password() + + # 1. Создаём LXC через ostemplate. start=0 — не запускаем, чтобы успеть + # задать пароль и диск нужного размера до старта. upid = px.nodes(node).lxc.post( vmid=new_vmid, hostname=name, @@ -95,12 +87,29 @@ def create_lxc( cores=cores, memory=memory_mb, swap=memory_mb, - rootfs=f"{storage}:{disk_gb}", - password=password, net0="name=eth0,bridge=vmbr0,ip=dhcp", unprivileged=1, + password=password, + start=0, ) _wait_task(px, node, upid) + + # 2. Задаём новый root-пароль через отдельный endpoint /passwd. + # Поле password в POST /lxc на некоторых версиях Proxmox игнорируется, + # поэтому дублируем через /passwd — это идемпотентная операция. + px.nodes(node).lxc(new_vmid).passwd.post(password=password) + + # 3. Создаём rootfs указанного размера (storage:size_G). + px.nodes(node).lxc(new_vmid).resize.put( + disk="rootfs", + size=f"{storage}:{disk_gb}", + ) + + # 4. Запускаем контейнер. + upid = px.nodes(node).lxc(new_vmid).status.start.post() + if upid: + _wait_task(px, node, upid) + return password @@ -151,7 +160,7 @@ def list_vm_templates(node: str = None) -> list: def list_lxc_templates(node: str = None) -> list: - """Возвращает архивные LXC-шаблоны из доступных хранилищ.""" + """Возвращает архивные LXC-шаблоны (vztmpl) из доступных хранилищ.""" node = node or settings.pve_node px = _client() result = [] @@ -251,7 +260,6 @@ def get_live_stats(vmid: int, node: str = None) -> dict: return {"cpu": 0, "mem_used": 0, "mem_total": 0, "uptime": 0, "status": "unknown"} -get_live_stats_lxc = get_live_stats _VALID_ACTIONS = {"start", "stop", "shutdown", "reboot"}