From c3ffed82b67ed1f32c5dcd89c6a500fb4f0daa40 Mon Sep 17 00:00:00 2001 From: host Date: Sun, 9 Aug 2026 16:43:35 +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=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BA=D0=BB=D0=BE=D0=BD=D0=B8=D1=80=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20LXC-=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=BF=D0=BE=20CTID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/proxmox_client.py | 84 ++++++++++------------------------- 1 file changed, 23 insertions(+), 61 deletions(-) diff --git a/backend/app/proxmox_client.py b/backend/app/proxmox_client.py index 249c7d7..0822f9a 100644 --- a/backend/app/proxmox_client.py +++ b/backend/app/proxmox_client.py @@ -15,14 +15,7 @@ def _client() -> ProxmoxAPI: if "!" not in settings.pve_token_name: raise RuntimeError("PVE_TOKEN_NAME должен иметь формат user@realm!token") user, token_name = settings.pve_token_name.split("!", 1) - return ProxmoxAPI( - parsed.hostname, - port=parsed.port or 8006, - user=user, - token_name=token_name, - token_value=settings.pve_token_value.get_secret_value(), - verify_ssl=settings.pve_verify_ssl, - ) + return ProxmoxAPI(parsed.hostname, port=parsed.port or 8006, user=user, token_name=token_name, token_value=settings.pve_token_value.get_secret_value(), verify_ssl=settings.pve_verify_ssl) def _wait_task(client: ProxmoxAPI, node: str, upid: str, timeout: int = 1800) -> None: @@ -43,67 +36,36 @@ def next_vmid() -> int: return int(_client().cluster.nextid.get()) -def provision_vm( - source_vmid: int, - vmid: int, - name: str, - cores: int, - memory_mb: int, - disk_gb: int, - username: str, - password: str, -) -> None: +def provision_vm(source_vmid: int, vmid: int, name: str, cores: int, memory_mb: int, disk_gb: int, username: str, password: str) -> None: """Клонирует cloud-init VM, настраивает ресурсы и запускает её.""" - client = _client() - node = settings.pve_node + client = _client(); node = settings.pve_node params = {"newid": vmid, "name": name, "full": 1} - if settings.pve_vm_storage: - params["storage"] = settings.pve_vm_storage - upid = client.nodes(node).qemu(source_vmid).clone.post(**params) - _wait_task(client, node, upid) - client.nodes(node).qemu(vmid).config.put( - cores=cores, - memory=memory_mb, - ciuser=username, - cipassword=password, - ipconfig0="ip=dhcp", - ) - # Увеличиваем диск только если шаблон меньше заданного размера. + if settings.pve_vm_storage: params["storage"] = settings.pve_vm_storage + _wait_task(client, node, client.nodes(node).qemu(source_vmid).clone.post(**params)) + client.nodes(node).qemu(vmid).config.put(cores=cores, memory=memory_mb, ciuser=username, cipassword=password, ipconfig0="ip=dhcp") config = client.nodes(node).qemu(vmid).config.get() for key in ("scsi0", "virtio0", "sata0", "ide0"): - value = config.get(key, "") - match = re.search(r"size=(\d+)G", value) + match = re.search(r"size=(\d+)G", config.get(key, "")) if match and disk_gb > int(match.group(1)): - client.nodes(node).qemu(vmid).resize.put( - disk=key, size=f"+{disk_gb - int(match.group(1))}G" - ) + client.nodes(node).qemu(vmid).resize.put(disk=key, size=f"+{disk_gb - int(match.group(1))}G") break client.nodes(node).qemu(vmid).status.start.post() -def provision_lxc( - source_template: str, - vmid: int, - name: str, - cores: int, - memory_mb: int, - disk_gb: int, - password: str, -) -> None: - """Создаёт LXC из CT-шаблона и запускает его с DHCP.""" - client = _client() - node = settings.pve_node - upid = client.nodes(node).lxc.post( - vmid=vmid, - hostname=name, - ostemplate=source_template, - cores=cores, - memory=memory_mb, - swap=memory_mb, - rootfs=f"{settings.pve_lxc_storage}:{disk_gb}", - password=password, - net0=f"name=eth0,bridge={settings.pve_bridge},ip=dhcp", - unprivileged=1, - ) +def provision_lxc_clone(source_vmid: int, vmid: int, name: str, cores: int, memory_mb: int, disk_gb: int, password: str) -> None: + """Клонирует готовый LXC-шаблон по CTID и запускает контейнер.""" + client = _client(); node = settings.pve_node + params = {"newid": vmid, "hostname": name, "full": 1} + if settings.pve_lxc_storage: params["storage"] = settings.pve_lxc_storage + _wait_task(client, node, client.nodes(node).lxc(source_vmid).clone.post(**params)) + client.nodes(node).lxc(vmid).config.put(cores=cores, memory=memory_mb, swap=memory_mb, password=password, net0=f"name=eth0,bridge={settings.pve_bridge},ip=dhcp") + client.nodes(node).lxc(vmid).resize.put(disk="rootfs", size=f"{disk_gb}G") + client.nodes(node).lxc(vmid).status.start.post() + + +def provision_lxc(source_template: str, vmid: int, name: str, cores: int, memory_mb: int, disk_gb: int, password: str) -> None: + """Создаёт LXC из архивного CT-шаблона и запускает его.""" + client = _client(); node = settings.pve_node + upid = client.nodes(node).lxc.post(vmid=vmid, hostname=name, ostemplate=source_template, cores=cores, memory=memory_mb, swap=memory_mb, rootfs=f"{settings.pve_lxc_storage}:{disk_gb}", password=password, net0=f"name=eth0,bridge={settings.pve_bridge},ip=dhcp", unprivileged=1) _wait_task(client, node, upid) client.nodes(node).lxc(vmid).status.start.post()