Storage API
GET /api/v1/storage
Section titled “GET /api/v1/storage”List Storage
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | Successful Response | any |
POST /api/v1/storage
Section titled “POST /api/v1/storage”Attach Storage
Attach a storage definition (doc 05 §Storage, doc 01 §5 “Add/edit storage”).
Synchronous: Proxmox returns no UPID for /storage, so there is no job and
therefore no jobs.params row holding body.config. The audit row is the
only durable trace, and write_audit runs it through redact(); nested
config.password included.
The response deliberately echoes NO config: a credential the caller just sent must not come back out of a GET the browser might cache or a screenshot someone pastes into a ticket.
capability="lifecycle": attaching/editing/detaching a storage POOL
DEFINITION needs Datastore.Allocate, a node-infrastructure privilege
none of the four capabilities carried until the per-capability token
sweep found the gap (host-token-privileges-step-one-report.md), the
same class of bug Sys.PowerMgmt was.
Request body (required), application/json, StorageAttachIn
| Field | Type | Required | Description |
|---|---|---|---|
config | object | no | |
host_id | integer | yes | |
storage | string | yes | |
type | string | yes |
Responses
| Status | Description | Schema |
|---|---|---|
| 201 | Successful Response | any |
| 422 | Validation Error | HTTPValidationError |
DELETE /api/v1/storage/{host_id}/{name}
Section titled “DELETE /api/v1/storage/{host_id}/{name}”Detach Storage
Owner, not admin (doc 05): detaching drops the definition while guest disks keep pointing at it, which is the one action here that can strand running guests. Upstream data is left in place; this is not a wipe.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host_id | path | integer | yes | |
name | path | string | yes |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | Successful Response | any |
| 422 | Validation Error | HTTPValidationError |
GET /api/v1/storage/{host_id}/{name}
Section titled “GET /api/v1/storage/{host_id}/{name}”Storage Detail
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host_id | path | integer | yes | |
name | path | string | yes | |
node | query | string | null | no |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | Successful Response | any |
| 422 | Validation Error | HTTPValidationError |
PATCH /api/v1/storage/{host_id}/{name}
Section titled “PATCH /api/v1/storage/{host_id}/{name}”Edit Storage
Audits the NAMES of the keys changed, never their values; the same rule settings.py::patch_settings follows, and the reason a rotated PBS password leaves a legible audit trail without leaving the password in it.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host_id | path | integer | yes | |
name | path | string | yes |
Request body (required), application/json, StorageEditIn
| Field | Type | Required | Description |
|---|---|---|---|
config | object | yes |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | Successful Response | any |
| 422 | Validation Error | HTTPValidationError |
GET /api/v1/storage/{host_id}/{name}/content
Section titled “GET /api/v1/storage/{host_id}/{name}/content”Storage Content
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host_id | path | integer | yes | |
name | path | string | yes | |
node | query | string | null | no | |
content | query | string | null | no |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | Successful Response | any |
| 422 | Validation Error | HTTPValidationError |
POST /api/v1/storage/{host_id}/{name}/content
Section titled “POST /api/v1/storage/{host_id}/{name}/content”Upload Content
Spool the body to disk, then hand the PATH to a job (doc 05 §Storage).
Never slurp the whole upload in one call: FastAPI’s UploadFile already spools to a SpooledTemporaryFile, and reading it all at once would materialise a multi-GB ISO in this process’s RAM. The 1 MiB loop below keeps peak memory flat regardless of file size. The cost, stated in services/storagejobs.py’s docstring too: the ISO crosses the wire twice (browser -> here -> PVE) and the Proxploy host needs transient free disk equal to the file size.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host_id | path | integer | yes | |
name | path | string | yes |
Request body (required), multipart/form-data, Body_upload_content_api_v1_storage__host_id___name__content_post
| Field | Type | Required | Description |
|---|---|---|---|
content | string | no | |
file | string | yes | |
node | string | null | no | |
overwrite | boolean | no |
Responses
| Status | Description | Schema |
|---|---|---|
| 202 | Successful Response | any |
| 422 | Validation Error | HTTPValidationError |
DELETE /api/v1/storage/{host_id}/{name}/content/{volid}
Section titled “DELETE /api/v1/storage/{host_id}/{name}/content/{volid}”Delete Content
:path because a volid is local:iso/ubuntu.iso; it carries a slash,
which a plain {volid} converter would refuse to match.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host_id | path | integer | yes | |
name | path | string | yes | |
volid | path | string | yes | |
node | query | string | null | no |
Responses
| Status | Description | Schema |
|---|---|---|
| 202 | Successful Response | any |
| 422 | Validation Error | HTTPValidationError |