Storage

Preview — pending review

This reference is generated from the platform API contract and is still under review. Operations, fields, and descriptions can change before publication.

Create a block volume

POST
/scopes/{scopeId}/storage/volumes

Provisions a new block volume in the active scope from the volume creation form: name, availability zone, size (1–16,384 GB), type (Premium SSD / Standard SSD / Standard HDD), source (empty, bootable image, or restore from an AVAILABLE snapshot), optional additional data disks (each with its own size and type), optional immediate attachment to an instance, and encryption at rest (AES-256, platform-managed key by default). On acceptance the volume becomes discoverable in the scoped list in state CREATING; when created from an image the size is raised to at least the image minimum. Validation: name must satisfy ResourceName (1–255 printable BMP characters, no leading/trailing whitespace — empty or whitespace-only → 422 VALIDATION_FAILED) and be unique within the project (duplicate → 409 CONFLICT). The character/length rule is checked SYNCHRONOUSLY: a name Cinder would refuse never reaches the provider, so it can no longer be accepted 202 and settle ERROR minutes later; sizeGb integer in [1, 16384] and ≥ the image minimum when sourceKind=image (→ 422); imageId/snapshotId required for their respective source kinds and must reference accessible resources — the snapshot must be AVAILABLE (unknown → 404 NOT_FOUND, not AVAILABLE → 409 CONFLICT); attachToInstanceId, when given, must reference a reachable instance in the scope (unknown → 404); every data disk must pass the same size/type checks (→ 422); block-storage quota for the subscription must cover root plus all data disks (→ 409 QUOTA_EXCEEDED); zonal capacity must be available (→ 409 CAPACITY_UNAVAILABLE); caller needs owner|admin|contributor on the scope (→ 403). Async & state: Asynchronous — returns 202 with the volume resource in its transitional CREATING state. Terminal states: AVAILABLE (detached), IN_USE (when attachToInstanceId was supplied) or ERROR. Progress is emitted as resource.updated SSE frames (kind storage.volume, patch {status, attachedTo, updatedAt}). Errors: 401 unauthenticated; 403 caller lacks create permission; 404 referenced image, snapshot or instance not found; 409 CONFLICT duplicate name or snapshot not AVAILABLE; 409 QUOTA_EXCEEDED block-storage quota exhausted; 409 CAPACITY_UNAVAILABLE no zonal capacity; 422 invalid name/size/type/source combination; 500 unexpected backend failure. Idempotency/Concurrency: Idempotency-Key is required; replaying the same key returns the original 202 response without provisioning a duplicate volume.

Authorization

bearerToken
headerAuthorizationBearer <token>

An API token (pc_live_…) or a service-account key (sak_live_…), created in Identity & Access Management and sent as Authorization: Bearer <token>. Requests are rate limited per credential and per tenant: every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a refused request gets 429 RATE_LIMITED with Retry-After.

Path Parameters

scopeId*string

Opaque ownership+authorization scope resolving to tenant + subscription + project.

Header Parameters

Idempotency-Key*string

Required: this operation creates a new resource asynchronously, so a retry without the key would create a second one. Same key+body within 24h replays the original result; the same key with a different body is 409 CONFLICT. Keys are unique per tenant (the same key in two tenants is two different requests). An API token or service-account (bearer) caller MUST send it -- a request without it is refused with 400 IDEMPOTENCY_KEY_REQUIRED (ErrIdempotencyKeyRequired); reuse the same key on every retry of one logical request. A console session gets one from the edge.

Formatuuid

Request Body

application/json
  1. body

Payload for creating a block volume (the volume creation form).

name*string

Volume name; must be non-empty and unique within the project.

Match^[^\p{C}\p{Z}\x{10000}-\x{10FFFF}](?:[^\p{C}\p{Zl}\p{Zp}\x{10000}-\x{10FFFF}]*[^\p{C}\p{Z}\x{10000}-\x{10FFFF}])?$
Length1 <= length <= 255
availabilityZone?string

Availability zone to place the volume in (e.g. ist-1a); defaults to the region's first zone.

sizeGb*integer

Root volume size in GB (1–16,384). A sourced volume must be at least as large as what it is built from — the source snapshot's size when sourceKind is snapshot, the image's minDiskGb when sourceKind is image — and a smaller value is rejected VALIDATION_FAILED naming the required minimum (Cinder cannot seed a volume smaller than its source). The size is never silently raised to the minimum.

Range1 <= value <= 16384
type*string

Volume performance type.

Value in"Standard SSD""Premium SSD""Standard HDD"
sourceKind?string

Source the volume is created from — blank, a bootable OS image, or an existing snapshot.

Default"empty"
Value in"empty""image""snapshot"
imageId?|

Image identifier; required when sourceKind=image. Must name an image the scope can see — an unknown id is rejected VALIDATION_FAILED (422) rather than accepted and settled ERROR.

snapshotId?|

Snapshot identifier (must be AVAILABLE); required when sourceKind=snapshot.

attachToInstanceId?|

Optional instance to attach the volume to immediately after creation; null/omitted creates it detached.

encrypted?boolean

REQUEST encryption at rest for the volume. Encryption is a property of the volume TYPE: the request is accepted only when the region offers encryption AND the chosen type has an encrypted variant there; otherwise it is rejected NOT_FOUND ("volume encryption at rest is not available …", field encrypted) rather than written in the clear. The provider's own verdict is checked after the create: a volume that comes out unencrypted is deleted and the operation fails. A volume created from an encrypted snapshot is encrypted regardless of this flag, and an encrypted volume is only ever retyped / cloned / restored onto an encrypted type. The encrypted variant bills at the tier's price. The value is never persisted or echoed back — Volume.encrypted on every read is what the provider reports. Defaults false.

Defaultfalse

Response Body

Volume creation accepted; returns the volume in its transitional CREATING state.

application/json
  1. response

Block volume read model as rendered by the Volumes page and the volume detail page.

origin?string

Where the resource was made -- portal for a create on the console, api for an object made straight against the OpenStack API (CLI, Terraform, the Kubernetes cloud provider) that discovery adopted. Informational; nothing behaves differently. Absent from a backend that predates it, which means portal.

Value in"portal""api""system""imported"
id*string

Volume identifier (e.g. vol-0a1b2c3d).

name*string

Volume display name.

status*string

Lifecycle status of the volume.

Value in"CREATING""AVAILABLE""IN_USE""AWAITING_TRANSFER""ERROR"
statusReason*|

Human-readable, customer-facing reason for the current status when it is a failure (e.g. "This request exceeds the quota available to this project. Free up existing resources or request a quota increase." on an ERROR volume); never raw provider text. Null while the volume is healthy or the failure carried no detail.

statusReasonCode*|

Machine-readable companion to statusReason: a small, OPEN vocabulary of codes the console can branch on without parsing the human text, deliberately a plain string rather than a closed enum so a code the client does not recognize yet degrades to the generic failure message. Today the only value is cancelled: the resource is in its failure state because its create operation was CANCELLED; a provider object the create had already built may be left in place, and the resource's DELETE removes it. Reported only while the resource is in that failure state; null otherwise.

sizeGb*integer

Provisioned size in GB (1–16,384).

type*|

Volume performance tier. Null when the volume sits on a provider volume type no platform tier maps to (e.g. a volume adopted from an imported project): the tier is then UNKNOWN and unpriced, never reported as a tier it is not. providerVolumeType carries the provider's own type name in that case.

providerVolumeType*|

The provider's (Cinder's) own volume type name, present only when type is null because no platform tier maps to it (an adopted volume on a legacy type). Null for a volume on a platform tier. Display-only: it has no price and cannot be requested.

attachedTo*|null

Instance attachment (instance id, name, device), or null when detached.

bootable*boolean

Whether the volume carries a bootable OS image.

encrypted*boolean

Whether the volume is encrypted at rest, DERIVED from the provider's own view of the volume (the volume type's encryption spec) — never from the create request. False until the provider confirms encryption, so this field never asserts a security property the platform did not actually deliver.

multiAttach*boolean

Allow attaching to more than one instance (RWX).

availabilityZone*string

Availability zone the volume lives in (e.g. ist-1a).

description*string

Operator-supplied description.

source*

Provenance of a block volume — empty, created from an image, restored from a snapshot, or cloned from another volume.

kmsKeyId*|

Customer-managed KMS key for envelope encryption; null when platform-managed or encryption is off.

keyRotationDays*integer

Automatic key-rotation period in days (0 = manual).

pricePerGbMonthlyCents*|

Price per GB per month in hundredths of the currency unit (an integer, not a Money object): the rate billing meters this volume's tier at for the volume's subscription, rounded down to the hundredth. Null when no price applies to the tier: there is no per-type default figure.

deletionProtection*boolean

Platform-owned deletion guard. While true, storage.volume.delete is refused with 409 DELETION_PROTECTED before any work starts; turn it off with the metadata PATCH, then delete. It guards the console and this API ONLY: Cinder has no lock, so an OpenStack API credential with Full access can still delete the volume directly. False for every volume unless a caller turned it on; the collector never writes it.

tags*array<>

Key-value pairs shown on the Tags tab; double as Cost Explorer dimensions.

createdAt*string

Creation timestamp (ISO 8601).

Formatdate-time
updatedAt*string

Last modification timestamp (ISO 8601).

Formatdate-time
curl -X POST "https://example.com/scopes/string/storage/volumes" \  -H "Idempotency-Key: 497f6eca-6276-4993-bfeb-53cbbbba6f08" \  -H "Content-Type: application/json" \  -d '{    "name": "string",    "sizeGb": 1,    "type": "Standard SSD"  }'
{  "origin": "portal",  "id": "string",  "name": "string",  "status": "CREATING",  "statusReason": "string",  "statusReasonCode": "string",  "sizeGb": 0,  "type": "Standard SSD",  "providerVolumeType": "string",  "attachedTo": {    "instanceId": "string",    "instanceName": "string",    "device": "string"  },  "bootable": true,  "encrypted": true,  "multiAttach": true,  "availabilityZone": "string",  "description": "string",  "source": {    "kind": "empty",    "ref": "string"  },  "kmsKeyId": "string",  "keyRotationDays": 0,  "pricePerGbMonthlyCents": 0,  "deletionProtection": true,  "tags": [    {      "key": "string",      "value": "string"    }  ],  "createdAt": "2019-08-24T14:15:22Z",  "updatedAt": "2019-08-24T14:15:22Z"}