Reverse-specification of glance — branch stable/2026.2
Branch
stable/2026.2@a3e5f490b7a2— repository https://opendev.org/openstack/glance — analysed on 2026-10-28
- Repository: https://opendev.org/openstack/glance (local clone) — specified branch:
stable/2026.2@a3e5f490b7a2(33.0.0-3-ga3e5f490b) — analysed on: 2026-10-28 - Scope: the whole service: glance-api (REST API, in-process asynchronous tasks, image cache), glance-scrubber, glance-manage; errors; interactions; scenarios; rewrite pack (step 8). Change history (step 7) not requested.
Overview
Glance is OpenStack's image service. It keeps the metadata of virtual machine images (formats, sizes, checksums, visibility, sharing, tags, properties) in a SQL database and delegates the data to pluggable stores through the separate glance_store library (local file system, Ceph RBD, Swift, S3, Cinder volumes, read-only HTTP). Clients create an image record, then send the data either in one request (PUT …/file) or through the interoperable import workflow (glance-direct, web-download, copy-image, glance-download), which runs as an asynchronous task inside the API worker. Nova downloads images to boot servers and uploads snapshots; Cinder creates volumes from images and images from volumes. Glance also hosts the metadata-definitions catalog (metadefs) and an optional per-node image cache. It has no RPC and no worker daemon besides the optional scrubber: everything runs in the API processes, which only publish notifications on the bus.
Architecture
flowchart LR
client[Clients: CLI, Horizon, Nova, Cinder] -->|HTTPS REST /v2| api[glance-api workers]
api -->|SQL| db[(MariaDB)]
api -->|glance_store: file / RBD / Swift / S3 / Cinder / HTTP| store[(Image stores)]
api -->|files| staging[(Staging dir, image cache)]
api -->|AMQP notifications| mq{{RabbitMQ}}
api -->|token validation, trusts, unified limits| ks[Keystone]
api -->|certificates, encryption keys| bbc[Barbican]
api -->|HTTP GET web-download| web[Remote HTTP servers]
api -->|REST glance-download| rg[Remote Glance]
api <-->|proxy to the worker holding staged data| api
scrub[glance-scrubber] -->|SQL| db
scrub -->|delete| storeProcesses
| Process | Entry point | Role | Listens to / consumes |
|---|---|---|---|
| glance-api | glance.cmd.api:main (pyproject.toml:71), WSGI glance/wsgi/api.py → glance/common/wsgi_app.py:113 | REST API; runs import, add-location and legacy tasks in its thread pool; image cache worker; staging cleanup at start-up | HTTP; no bus consumer |
| glance-scrubber | glance.cmd.scrubber:main (pyproject.toml:79) | deletes the data of pending_delete images (delayed delete), once or as a daemon | timer (wakeup_time) |
| glance-manage | glance.cmd.manage:main (pyproject.toml:77) | schema migrations, purge, metadefs load/export | CLI |
| glance-status | glance.cmd.status:main (pyproject.toml:80) | upgrade checks | CLI |
| glance-cache-prefetcher / -pruner / -cleaner / -manage | pyproject.toml:72-75 | deprecated cache maintenance (replaced by /v2/cache) | cron / CLI |
| glance-replicator, glance-control | pyproject.toml:76, pyproject.toml:78 | copy images between Glances; start/stop daemons (legacy tools) | CLI |
External dependencies
| System | Protocol | Library | Configuration | Usage |
|---|---|---|---|---|
| MariaDB / MySQL | SQL | oslo.db, SQLAlchemy | [database]/connection | all metadata, tasks, metadefs, cache metadata |
| Image stores | file, RADOS, Swift/S3 REST, Cinder, HTTP | glance_store | [glance_store] or enabled_backends | image data |
| RabbitMQ | AMQP (notifications only) | oslo.messaging | [oslo_messaging_notifications] | image.*, task.*, metadef_* events |
| Keystone | REST | keystonemiddleware, keystoneauth, oslo.limit | [keystone_authtoken], [oslo_limit] | authentication, trusts, unified limits |
| Barbican | REST | castellan, cursive | [key_manager] | image signature certificates, Cinder encryption keys |
qemu-img | process | oslo.concurrency | [image_conversion] | conversion import plugin |
Details: 03-interactions_stable-2026.2.md.
Files
| File | Content |
|---|---|
| 01-rest-api_stable-2026.2.md | the 80 routed operations + 7 legacy cache routes, functional and technical sheets, lifecycles of images, tasks and members |
| 02-errors_stable-2026.2.md | error body, exception → HTTP translation, catalogue, asynchronous errors, logs |
| 03-interactions_stable-2026.2.md | database, stores, notifications, outbound REST, files and processes |
| 04-scenarios_stable-2026.2.md | upload, glance-direct import across workers, multi-store web-download, delayed delete, Nova snapshot via locations |
| 05-async-processing_stable-2026.2.md | import, add-location and legacy tasks, lock expiry, cache worker, staging cleanup, scrubber |
| 07-rewrite-pack_stable-2026.2.md | rewrite pack: HTTP behaviour, data path, client expectations, database, policies, glance_store contract, conformance |
| _rewrite/ | machine-readable contracts and the recorded exchanges |
| _inventory/ | raw inventory |
Key figures
- 80 routed REST operations (78 under
/v2) + 7 legacy cache-management routes; 79 operations documented in the api-ref; no microversions (/v2.0…/v2.18are aliases). - 67 default policy rules; 86 exception classes in
glance/common/exception.py, 287 explicit exception → HTTP conversions. - 15 tables; models and migrations identical.
- 0 RPC methods, 0 bus consumers, 33 notification event types; 3 asynchronous task types run in-process; 1 timer daemon (scrubber).
- Conformance data: 2441 exchanges recorded from 239 functional tests (238 pass with the recorder); 288 distinct error responses observed.
Points of attention
- Asynchronous work lives in the API worker that accepted the request. If that worker dies, the task stays
processingand the image keeps its import lock until a new request steals it after 60 minutes (120 forpending). Staged data is on the worker's local disk; other workers proxy to it throughworker_self_reference_url, which must be set per worker (05, 04). - Errors have no machine-readable code: webob text, HTML or JSON pages; clients parse statuses only, and sometimes texts (02).
- Same exception, different statuses:
InvalidImageStatusTransitionis 400 on delete and actions but 409 on upload and import;Invalidbecomes 404 on delete-from-store; download of an image whose data vanished answers 204 (02). - 403 hidden as 404 on images and metadef namespaces the caller cannot see.
- The version document gates client features: glanceclient only calls the tasks, cache and locations APIs when
/versionslistsv2.12,v2.14,v2.17; Glance listsv2.12only with multi-store andv2.14only with the cache enabled (07 § 4). - Unknown list parameters filter on properties instead of being rejected.
- **
DELETE /v2/cachedrops the counts** it computes (204 forced by the serializer). - Metadef namespace creation is not atomic: if an embedded child fails validation (400), the namespace stays created.
- Pipelines without authentication (
default,caching,cachemanagementflavours) make every caller admin; only thekeystone*flavours are safe. - **Over-long
X-Openstack-Request-ID**: the context middleware returns instead of raising its 431 error [inferred effect, 07 § 2.3]. - Synchronous upload of large images keeps an HTTP request and a token alive for the whole transfer; Glance uses Keystone trusts to finish the database update after token expiry.
- Delete with RBD clones returns 409 (
HasSnapshot/InUseByStore) and leaves the image active.
Blind spots / [inferred]
- Store drivers are in
glance_storeand were only read for their contract (07 § 6), not specified driver by driver. - Exact Keystone requests made by oslo.limit and castellan are [inferred] from the library roles, not traced.
glance-replicator,glance-controland the deprecated cache commands are only listed.- Property protections were not exercised with a real rules file.
- The recorded exchanges come from the functional tests' pipelines without keystonemiddleware (identity headers set by the tests).
- Change history (step 7) was not produced: run it on request to get the change specifications of the branch and a carry-over plan.
Source: reverse-spec-glance/00-summary_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.