Skip to content

feat(v1/proxmox): storage + per-VM snapshot endpoints (direct httpx)#99

Merged
pparage merged 10 commits into
devfrom
feature/v1-proxmox-readops
Jun 26, 2026
Merged

feat(v1/proxmox): storage + per-VM snapshot endpoints (direct httpx)#99
pparage merged 10 commits into
devfrom
feature/v1-proxmox-readops

Conversation

@pparage

@pparage pparage commented Jun 25, 2026

Copy link
Copy Markdown
Member

Summary

Adds v1 direct-httpx Proxmox endpoints for storage and per-VM snapshots, replacing the v0 Ansible-backed equivalents. Advances #87 (migrate remaining v0 admin/proxmox ops to v1). All endpoints address Proxmox by registered host_id (node derived from the host record — no proxmox_node param) and talk to the PVE REST API directly, mirroring the existing vms.py.

First commit extracts the shared host/PVE helpers (_session, _get_host, _auth_headers, _assert_vmid_safe, _unreachable, new _raise_for_pve) into _helpers.py, removing prior duplication between vms.py and hosts.py.

Endpoints

Storage:

  • GET /v1/proxmox/hosts/{host_id}/storagePage[StoragePool]
  • GET /v1/proxmox/hosts/{host_id}/storage/{store}/content?content=iso|vztmplPage[StorageContent] (derives name from volid — PVE doesn't return it)
  • POST /v1/proxmox/hosts/{host_id}/storage/{store}/download-urlVmActionResult (UPID)

Per-VM snapshots (qemu + lxc):

  • GET /v1/proxmox/hosts/{host_id}/vms/{vmid}/snapshotsPage[SnapshotItem] (filters PVE's synthetic current)
  • POST /v1/proxmox/hosts/{host_id}/vms/{vmid}/snapshotsVmActionResult (UPID)
  • DELETE /v1/proxmox/hosts/{host_id}/vms/{vmid}/snapshots/{name}VmActionResult (UPID)
  • POST /v1/proxmox/hosts/{host_id}/vms/{vmid}/snapshots/{name}/rollbackVmActionResult (UPID) — vmid-guarded (protected VMIDs refused before any outbound call)

Security hardening

A review pass added input validation: Path(pattern=...) constraints on {store} and {name} (block path-segment injection into outbound URLs), an http(s)-only scheme guard on download-url url (SSRF), and a bare-filename guard on filename (file-plant).

Notes

Tests

  • 33/33 proxmox route suite green (tests/routes/test_proxmox_{storage,snapshots,vms,hosts}.py), house pattern (_boot temp-sqlite + faked httpx.AsyncClient).
  • Two repo-wide failures (test_alembic, test_expand_replication) are pre-existing — reproduced at the base commit and untouched by this diff (which is confined to 9 proxmox files).

Follow-up (separate PR)

deployer-ui: repoint storage.* / snapshot.* in src/services/proxmox/api.ts at these v1 paths (.items-unwrap the Page), drop proxmox_node args.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 35ee70a318

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/routes/v1/proxmox/snapshots.py Outdated
Comment on lines +73 to +74
if body.vmstate is not None:
form["vmstate"] = 1 if body.vmstate else 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid sending vmstate for LXC snapshots

When callers create an LXC snapshot (?vmtype=lxc) and include vmstate, this branch forwards vmstate to /lxc/.../snapshot; PVE rejects that qemu-only option, so the newly advertised LXC snapshot path returns a 502 instead of creating the snapshot. The current community.proxmox implementation handles the same distinction by omitting vmstate for vm['type'] == 'lxc' (https://raw.githubusercontent.com/ansible-collections/community.proxmox/main/plugins/modules/proxmox_snap.py), so gate this field on vmtype == "qemu" or reject the combination before calling PVE.

Useful? React with 👍 / 👎.

PVE rejects vmstate on /lxc/.../snapshot, so forwarding it broke the
vmtype=lxc create path (502). Gate the field on vmtype==qemu, matching
community.proxmox proxmox_snap behavior.
@pparage pparage self-assigned this Jun 26, 2026
@pparage pparage merged commit 00833bf into dev Jun 26, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant