from .config import settings from .proxmox_client import _client, _wait_task _VALID_ACTIONS = {"start", "stop", "shutdown", "reboot"} def _is_not_found(error: Exception) -> bool: """Определяет ответ Proxmox об отсутствующем госте.""" if getattr(error, "status_code", None) == 404: return True response = getattr(error, "response", None) return getattr(response, "status_code", None) == 404 def _endpoint(client, guest_type: str, vmid: int): """Возвращает endpoint VM или LXC.""" node = settings.pve_node return client.nodes(node).qemu(vmid) if guest_type == "vm" else client.nodes(node).lxc(vmid) def delete_guest(guest_type: str, vmid: int) -> None: """Останавливает и удаляет VM/LXC, ожидая завершения задач Proxmox.""" client = _client() node = settings.pve_node endpoint = _endpoint(client, guest_type, vmid) try: current = endpoint.status.current.get() except Exception as error: if _is_not_found(error): return raise if current.get("status") == "running": stop_upid = endpoint.status.stop.post() if stop_upid: _wait_task(client, node, stop_upid) try: delete_upid = endpoint.delete() except Exception as error: if _is_not_found(error): return raise if delete_upid: _wait_task(client, node, delete_upid) def guest_action(guest_type: str, vmid: int, action: str) -> None: """Выполняет start, stop, shutdown или reboot.""" if action not in _VALID_ACTIONS: raise ValueError("Недопустимое действие") client = _client() node = settings.pve_node endpoint = _endpoint(client, guest_type, vmid) upid = getattr(endpoint.status, action).post() if upid: _wait_task(client, node, upid, timeout=300) def get_live_stats(guest_type: str, vmid: int) -> dict: """Возвращает CPU, RAM, uptime и фактический статус гостя.""" client = _client() status = _endpoint(client, guest_type, vmid).status.current.get() return { "status": status.get("status", "unknown"), "cpu_pct": round(float(status.get("cpu", 0)) * 100, 1), "memory_used_bytes": int(status.get("mem", 0)), "memory_total_bytes": int(status.get("maxmem", 0)), "disk_used_bytes": int(status.get("disk", 0)), "disk_total_bytes": int(status.get("maxdisk", 0)), "uptime_seconds": int(status.get("uptime", 0)), }