Удалить машину можно в любом состоянии: работающая выключается, пока идёт задача удаление ждёт, пробросы портов машины удаляются вместе с ней

Этот коммит содержится в:
2026-09-27 17:58:07 +09:00
родитель f31b4ade1d
Коммит ec9428c2eb
5 изменённых файлов: 64 добавлений и 7 удалений
+9 -2
Просмотреть файл
@@ -2094,14 +2094,21 @@ def vm_action(request: Request, name: str, action: str):
if action in ("shutdown", "destroy", "delete"):
backups.cancel_late_restart(name)
if action == "delete":
if vm_state(name) == "running":
import core
busy = core.active_operations_for(name)
if busy:
return redirect_with_message(f"/vm/{name}", "error", f"С машиной сейчас идёт задача «{busy[0].get('title') or 'операция'}». Дождитесь её завершения и удалите машину снова.")
if core.vm_is_running(name): # и на паузе тоже: undefine активной машины оставил бы её работать без настроек
run_cmd(["virsh", "destroy", name], timeout=20)
# --nvram: UEFI machines keep firmware variables that block a plain undefine.
result = run_cmd(["virsh", "undefine", name, "--remove-all-storage", "--nvram", "--managed-save", "--snapshots-metadata", "--checkpoints-metadata"], timeout=120)
if not result["ok"]:
return redirect_with_message(f"/vm/{name}", "error", f"Не удалось удалить машину: {virsh_error(result)}")
network_core.release_nat_address(name)
return redirect_with_message("/", "message", f"Машина {name} удалена")
removed = network_core.remove_vm_forwards(name)
message = f"Машина {name} удалена" + (f", вместе с ней убраны пробросы портов: {removed}" if removed else "")
return redirect_with_message("/", "message", message)
if action not in allowed:
return JSONResponse({"ok": False, "error": "Unsupported action"}, status_code=400)
result = run_cmd(allowed[action], timeout=30)