fix(vm_provision_mixin): upload Cloud-Init snippet as a real multipart file
proxmoxer only builds a multipart request for io.IOBase values passed
as kwargs; a plain filename string (plus a nonexistent "data" field,
as the old code sent) goes out as an ordinary form-urlencoded POST
instead. Real Proxmox's /storage/{s}/upload endpoint expects an actual
file upload for "filename" and responds to anything else by closing
the connection with no HTTP response at all.
Found live: the VM shell, disk import, and node-scoped storage
selection all succeeded, then create_vm_from_cloud_init failed with
requests.exceptions.ConnectionError / RemoteDisconnected right at the
snippet upload step.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
import logging
|
||||
import time
|
||||
import yaml
|
||||
@@ -337,11 +338,18 @@ class ProxmoxVMProvisionMixin:
|
||||
filename = f"{vmid}-user-data.yaml"
|
||||
_logger.debug(f"Uploading Cloud-Init snippet {filename} to {snippet_storage}")
|
||||
|
||||
# Upload to snippet storage
|
||||
# Upload to snippet storage. Proxmox's upload endpoint expects the
|
||||
# "filename" parameter to BE the file (multipart), not a name
|
||||
# string with separate content — proxmoxer only builds a
|
||||
# multipart request when the value is an io.IOBase instance,
|
||||
# otherwise it silently sends everything as a plain
|
||||
# form-urlencoded POST, which real Proxmox rejects by dropping
|
||||
# the connection (RemoteDisconnected, no HTTP response at all).
|
||||
file_obj = io.BytesIO(user_data_yaml.encode("utf-8"))
|
||||
file_obj.name = filename
|
||||
self._node_api().storage(snippet_storage).upload.post(
|
||||
content="snippets",
|
||||
filename=filename,
|
||||
data=user_data_yaml,
|
||||
filename=file_obj,
|
||||
)
|
||||
|
||||
# Step 7: Configure Cloud-Init references and SSH keys
|
||||
|
||||
Reference in New Issue
Block a user