From 3181ade72846b3cb4529a2efb2c3683cef0d5a06 Mon Sep 17 00:00:00 2001 From: Christian Manivong Date: Wed, 8 Jul 2026 19:54:05 +0200 Subject: [PATCH] fix(vm_provision_mixin): destroy_vm's delete call rejected by Proxmox (400) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Passed destroy_unreferenced_disks (underscore) as a kwarg to proxmoxer's delete(), but Proxmox's actual DELETE /nodes/{node}/qemu/{vmid} parameter is hyphenated (destroy-unreferenced-disks). proxmoxer forwards kwargs to the request verbatim with no underscore-to-hyphen translation, so Proxmox rejected every call with "property is not defined in schema" before ever touching the VM — the VM stayed fully intact (config, disks) despite the caller believing destroy had at least been attempted. Fixed by building the params as a dict (bypassing the Python-identifier restriction) with the correct hyphenated key. Co-Authored-By: Claude Sonnet 5 --- napalm_proxmox/vm_provision_mixin.py | 13 +++++++++---- tests/test_vm_provision_mixin.py | 5 +++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/napalm_proxmox/vm_provision_mixin.py b/napalm_proxmox/vm_provision_mixin.py index 3bd2344..7c9935e 100644 --- a/napalm_proxmox/vm_provision_mixin.py +++ b/napalm_proxmox/vm_provision_mixin.py @@ -476,11 +476,16 @@ class ProxmoxVMProvisionMixin: _logger.debug(f"VM {vmid} stop failed (may already be stopped): {e}") # Step 2: Delete VM + # Proxmox's API parameter is hyphenated (destroy-unreferenced-disks), + # not a valid Python identifier — proxmoxer forwards kwargs to the + # request verbatim with no underscore-to-hyphen translation, so this + # must be built as a dict and unpacked rather than passed as a kwarg. _logger.debug(f"Deleting VM {vmid} configuration and disks") - self._node_api().qemu(vmid_int).delete( - purge=1, - destroy_unreferenced_disks=1 if remove_disk else 0, - ) + delete_params = { + "purge": 1, + "destroy-unreferenced-disks": 1 if remove_disk else 0, + } + self._node_api().qemu(vmid_int).delete(**delete_params) # Step 3: Clean up Cloud-Init snippets # (This is best-effort; snippet files may be unreachable if storage is unavailable) diff --git a/tests/test_vm_provision_mixin.py b/tests/test_vm_provision_mixin.py index 12e9b07..14eb99f 100644 --- a/tests/test_vm_provision_mixin.py +++ b/tests/test_vm_provision_mixin.py @@ -451,6 +451,11 @@ def test_destroy_vm_success(): mixin.destroy_vm("101", remove_disk=True, timeout=60) assert mock_vm.delete.called + # Proxmox's API parameter is hyphenated; passing the underscore form + # (a Python-identifier-friendly typo) gets silently rejected by Proxmox + # with a 400 "property is not defined in schema" instead of deleting. + _, delete_kwargs = mock_vm.delete.call_args + assert delete_kwargs == {"purge": 1, "destroy-unreferenced-disks": 1} def test_destroy_vm_already_stopped():