Learn OpenStack · core/storage/image
Glance Operations
Upload a Local Image
The most direct method: read image data from a local file and push it directly to Glance.
openstack image create \
--disk-format qcow2 \
--container-format bare \
--file ubuntu-24.04.qcow2 \
--public \
ubuntu-24.04
With additional properties set at creation time:
openstack image create \
--disk-format qcow2 \
--container-format bare \
--file ubuntu-24.04.qcow2 \
--public \
--property hw_disk_bus=virtio \
--property hw_vif_model=virtio \
--property os_distro=ubuntu \
--property os_version=24.04 \
--min-disk 2 \
--min-ram 512 \
ubuntu-24.04
Common image create flags:
| Flag | Description |
|---|---|
--disk-format |
Required. qcow2, raw, vmdk, vhd, vhdx, iso, etc. |
--container-format |
Required. Usually bare |
--file |
Path to local file to upload |
--public |
Set visibility to public (admin only) |
--private |
Set visibility to private (default) |
--community |
Set visibility to community |
--shared |
Set visibility to shared |
--protected |
Mark image as protected (cannot be deleted) |
--unprotected |
Mark image as unprotected |
--property key=value |
Set an image property |
--tag |
Add a tag |
--min-disk |
Minimum disk size in GB required to boot |
--min-ram |
Minimum RAM in MB required to boot |
--project |
Create in a specific project (admin only) |
--project-domain |
Domain of the project |
Import an Image with Interoperable Import
The interoperable import workflow is the recommended approach for images that are not available as local files — for example, images hosted on external URLs or staged in Glance's web-upload cache.
Import from a URL (web-download)
openstack image create \
--disk-format qcow2 \
--container-format bare \
--uri https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img \
--import \
ubuntu-24.04
Glance fetches the image data from the URL server-side. The client does not stream the data — Glance's import worker downloads it directly to the store. This avoids saturating the client's uplink for large images.
Import via glance-direct (stage then import)
Stage the image data to Glance's staging area first, then trigger the import:
# Step 1: Create the image record (no data yet; status = queued)
openstack image create \
--disk-format qcow2 \
--container-format bare \
ubuntu-24.04-staged
# Step 2: Stage the data (PUT to /v2/images/<id>/stage)
glance image-stage --file ubuntu-24.04.qcow2 <image-id>
# or via curl:
curl -X PUT "http://glance:9292/v2/images/<image-id>/stage" \
-H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary @ubuntu-24.04.qcow2
# Step 3: Trigger the import
glance image-import --import-method glance-direct <image-id>
# or via openstack CLI (if import subcommand available):
openstack image create --import <image-id>
Copy an Image Between Stores (copy-image)
When multiple stores are configured, copy an existing active image to an additional store:
glance image-import --import-method copy-image \
--stores rbd,swift \
<image-id>
This is used in multi-store deployments to replicate an image to edge stores after initial upload to a central store.
List Images
# List images visible to the current project
openstack image list
# Include community images
openstack image list --community
# Include shared images
openstack image list --shared
# List public images only
openstack image list --public
# List private images only
openstack image list --private
# Filter by status
openstack image list --status active
# Filter by format
openstack image list --disk-format qcow2
# Long format (includes more columns)
openstack image list --long
# All images across all projects (admin)
openstack image list --all-projects
# Filter by property
openstack image list --property os_distro=ubuntu
# Filter by tag
openstack image list --tag production
Show Image Details
openstack image show ubuntu-24.04
openstack image show <image-id>
Output includes: id, name, disk_format, container_format, size, status, visibility, protected, min_disk, min_ram, owner, created_at, updated_at, tags, and all custom properties.
Delete Images
# Delete by name or ID
openstack image delete ubuntu-24.04
openstack image delete <image-id>
# Delete multiple images
openstack image delete img1 img2 img3
# Delete is blocked if protected=true; unprotect first:
openstack image set --unprotected ubuntu-24.04
openstack image delete ubuntu-24.04
Update Image Metadata
# Rename an image
openstack image set --name ubuntu-24.04-LTS ubuntu-24.04
# Change visibility (admin required for public)
openstack image set --public ubuntu-24.04
openstack image set --private ubuntu-24.04
openstack image set --community ubuntu-24.04
# Set protection
openstack image set --protected ubuntu-24.04
openstack image set --unprotected ubuntu-24.04
# Add or update properties
openstack image set --property hw_disk_bus=virtio ubuntu-24.04
openstack image set --property hw_vif_model=virtio --property os_distro=ubuntu ubuntu-24.04
# Remove a property
openstack image unset --property hw_disk_bus ubuntu-24.04
# Add tags
openstack image set --tag production --tag tested ubuntu-24.04
# Remove tags
openstack image unset --tag tested ubuntu-24.04
# Deactivate (blocks non-admin downloads and Nova use)
openstack image set --deactivate ubuntu-24.04
# Reactivate
openstack image set --reactivate ubuntu-24.04
Save (Download) an Image
# Download to a local file
openstack image save --file downloaded.qcow2 ubuntu-24.04
# Download by ID
openstack image save --file /tmp/image.qcow2 <image-id>
Deactivated images cannot be downloaded by non-admin users. Admins can still download them.
Manage Image Sharing
Images with visibility = shared can be explicitly shared with other projects using the image member API.
# Share an image with a target project
openstack image add project ubuntu-24.04 <target-project-id>
# The target project must accept the shared image
# (run as a user in the target project)
openstack image set --status accepted ubuntu-24.04
# Or reject it
openstack image set --status rejected ubuntu-24.04
# List members of a shared image (owner view)
openstack image member list ubuntu-24.04
# Remove a project from the member list
openstack image remove project ubuntu-24.04 <target-project-id>
Member status values:
| Status | Meaning |
|---|---|
pending |
Owner shared the image; member has not yet accepted |
accepted |
Member accepted the share; image appears in their image list |
rejected |
Member rejected the share; image does not appear in their image list |
Manage Image Properties
Set Properties at Create or Update Time
openstack image set --property hw_disk_bus=virtio ubuntu-24.04
openstack image set --property hw_vif_model=virtio ubuntu-24.04
openstack image set --property hw_firmware_type=uefi ubuntu-24.04
openstack image set --property hw_machine_type=q35 ubuntu-24.04
openstack image set --property os_type=linux ubuntu-24.04
openstack image set --property os_distro=ubuntu ubuntu-24.04
openstack image set --property os_version=24.04 ubuntu-24.04
openstack image set --property os_admin_user=ubuntu ubuntu-24.04
openstack image set --property os_require_quiesce=yes ubuntu-24.04
Remove Properties
openstack image unset --property hw_disk_bus ubuntu-24.04
Show All Properties
openstack image show ubuntu-24.04
# Properties are shown in the 'properties' column
Use the Task API
The task API (/v2/tasks) is used internally by the import workflow. Operators can inspect tasks to debug stuck imports.
# List tasks (requires glance CLI)
glance task-list
# Show a specific task
glance task-show <task-id>
Task types:
| Type | Description |
|---|---|
import |
Created for each image-import invocation |
Task statuses: pending, processing, success, failure
Run Database Maintenance
# Sync the database schema
glance-manage db_sync
# Load metadef namespace definitions from bundled JSON files
glance-manage db_load_metadefs
# Unload all metadef definitions
glance-manage db_unload_metadefs
# Export metadef definitions to JSON
glance-manage db_export_metadefs
# Purge deleted image records (logical deletes older than N days)
glance-manage db_purge --age_in_days 30
# Show current DB version
glance-manage db_version
Configuration Reference
Glance configuration lives in /etc/glance/glance-api.conf. The file uses oslo.config INI format.
[DEFAULT]
[DEFAULT]
# Host the API binds to
bind_host = 0.0.0.0
bind_port = 9292
# Worker processes (0 = auto-detect CPU count)
workers = 4
# Logging
log_file = /var/log/glance/api.log
log_dir = /var/log/glance
# Enable delayed delete (data kept until scrubber runs)
delayed_delete = false
scrub_time = 43200 # seconds before scrubber deletes data
scrubber_datadir = /var/lib/glance/scrubber
# Show image count in list responses
send_identity_headers = true
# Maximum image size in bytes (0 = unlimited)
image_size_cap = 1099511627776 # 1 TB
# Enable image import
enable_v2_api = true
enable_image_import = true
# Staging area for interoperable import
node_staging_uri = file:///var/lib/glance/staging
# Use this to override the public endpoint reported in API responses
public_endpoint = https://glance.example.com
[glance_store]
[glance_store]
# Comma-separated list of enabled stores
stores = file,http
# Default store for new images
default_store = file
# Multiple store configuration (multi-store feature)
enabled_backends = fast:file,slow:file
# --- File store ---
filesystem_store_datadir = /var/lib/glance/images/
# Multiple directories (weight-based selection)
filesystem_store_datadirs = /var/lib/glance/images/:200,/mnt/nfs/glance/:100
# --- Swift store ---
swift_store_auth_address = http://keystone:5000/v3
swift_store_auth_version = 3
swift_store_user = service:glance
swift_store_key = <password>
swift_store_container = glance
swift_store_create_container_on_put = true
swift_store_large_object_size = 5120
swift_store_large_object_chunk_size = 200
swift_store_multi_tenant = false
# --- RBD/Ceph store ---
rbd_store_pool = images
rbd_store_user = glance
rbd_store_ceph_conf = /etc/ceph/ceph.conf
rbd_store_chunk_size = 8
# --- S3 store ---
s3_store_host = https://s3.amazonaws.com
s3_store_access_key = <access-key>
s3_store_secret_key = <secret-key>
s3_store_bucket = glance-images
s3_store_create_bucket_on_put = true
s3_store_large_object_size = 100
s3_store_large_object_chunk_size = 10
# --- Cinder store ---
cinder_store_auth_address = http://keystone:5000/v3
cinder_store_user_name = glance
cinder_store_password = <password>
cinder_store_project_name = service
cinder_volume_type = image-tier
cinder_store_replication_enabled = false
[database]
[database]
connection = mysql+pymysql://glance:<password>@db-host/glance
max_pool_size = 10
max_overflow = 20
pool_timeout = 10
[keystone_authtoken]
[keystone_authtoken]
www_authenticate_uri = http://keystone:5000
auth_url = http://keystone:5000
memcached_servers = memcache1:11211,memcache2:11211
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = glance
password = <glance-service-password>
[paste_deploy]
[paste_deploy]
flavor = keystone
[image_format]
[image_format]
# Disk formats that Glance will accept on upload
disk_formats = ami,ari,aki,vhd,vhdx,vmdk,raw,qcow2,vdi,iso,ploop
# Container formats Glance will accept
container_formats = ami,ari,aki,bare,ovf,ova,docker
[task]
[task]
# Number of seconds a task is retained after completion before being purged
task_time_to_live = 2592000 # 30 days
# Executor type for tasks: taskflow (default)
task_executor = taskflow
# Logging for tasks
work_dir = /var/lib/glance/work
# Number of taskflow workers
eventlet_executor_pool_size = 1000
[taskflow_executor]
[taskflow_executor]
# Engine mode: serial (default) or parallel
engine_mode = serial
# Maximum number of concurrent workers in parallel mode
max_workers = 10
[oslo_messaging_rabbit] (for task notifications)
[oslo_messaging_rabbit]
rabbit_host = rabbitmq
rabbit_port = 5672
rabbit_userid = openstack
rabbit_password = <password>
rabbit_virtual_host = /
Inspect Glance from the REST API Directly
export TOKEN=$(openstack token issue -f value -c id)
export GLANCE=http://glance:9292
# List images
curl -s -H "X-Auth-Token: $TOKEN" $GLANCE/v2/images | python3 -m json.tool
# Show image
curl -s -H "X-Auth-Token: $TOKEN" $GLANCE/v2/images/<image-id> | python3 -m json.tool
# Upload image data (PUT)
curl -X PUT $GLANCE/v2/images/<image-id>/file \
-H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary @image.qcow2
# Download image data
curl -H "X-Auth-Token: $TOKEN" \
$GLANCE/v2/images/<image-id>/file -o downloaded.qcow2
# Create an image record (POST)
curl -X POST $GLANCE/v2/images \
-H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "ubuntu-24.04",
"disk_format": "qcow2",
"container_format": "bare",
"visibility": "public"
}'
# Update image properties (PATCH)
curl -X PATCH $GLANCE/v2/images/<image-id> \
-H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/openstack-images-v2.1-json-patch" \
-d '[
{"op": "add", "path": "/hw_disk_bus", "value": "virtio"},
{"op": "replace", "path": "/name", "value": "ubuntu-24.04-LTS"}
]'
# Trigger import (web-download)
curl -X POST $GLANCE/v2/images/<image-id>/import \
-H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"method": {"name": "web-download", "uri": "https://example.com/image.qcow2"}
}'
# List tasks
curl -s -H "X-Auth-Token: $TOKEN" $GLANCE/v2/tasks | python3 -m json.tool
# Show task
curl -s -H "X-Auth-Token: $TOKEN" $GLANCE/v2/tasks/<task-id> | python3 -m json.tool