Reverse-specification of magnum — branch stable/2026.2
Branch
stable/2026.2@1910928b7d9f— repository https://opendev.org/openstack/magnum — analysed on 2026-11-09
- Repository: https://opendev.org/openstack/magnum — specified branch:
stable/2026.2(Magnum 23.0.0 + backports) @1910928b7d9f— analysed on: 2026-11-09 - Scope: the whole project (REST API, conductor, periodic tasks, errors, interactions), plus a rewrite pack for a Go re-implementation (OpenKeel), plus the Cluster API driver magnum-cluster-api v0.39.0 (
066fdc2), which builds the clusters. Change history of the 2026.2 cycle (22.0.0.0rc1..stable/2026.2, 60 commits) in 06.
Overview
Magnum is OpenStack's "Container Infrastructure Management" service (container-infra): it creates and manages Kubernetes clusters for projects. It has two processes. magnum-api (pecan + WSME, port 9511) validates requests and either answers from the database or sends the work to magnum-conductor over RabbitMQ. The conductor creates the cluster rows and their certificates, calls a cluster driver, and polls the driver every 10 seconds to move clusters to their final status. In 2026.2 Magnum ships no driver at all: the legacy Heat driver was deprecated in 2025.1 and removed in this release (commit 31b8432). Clusters are built by an out-of-tree driver loaded through the magnum.drivers entry point, in practice one of the two Cluster API drivers. Magnum also generates three CAs per cluster and signs user certificates, and it polls each cluster's Kubernetes API for health.
Architecture
flowchart LR
client[Client / Skyline / CLI / autoscaler / auto-healer] -->|HTTPS REST :9511| api[magnum-api]
api -->|token validation| ks[Keystone]
api -->|validation REST| os[Glance / Nova / Neutron]
api -->|AMQP cast/call topic magnum-conductor| mq{{RabbitMQ}}
mq --> cond[magnum-conductor]
api -->|SQL| db[(MariaDB)]
cond -->|SQL| db
cond -->|certificates| bb[Barbican]
cond -->|notifications magnum.cluster.*| mq
cond -->|driver API| drv[magnum-cluster-api driver]
drv -->|HTTPS| mgmt[Management cluster: CAPI + CAPO]
mgmt -->|Nova / Neutron / Octavia / Cinder| cloud[OpenStack]
cond -->|HTTPS mTLS health| k8s[Workload cluster API]Processes
| Process | Entry point | Role | Listens to / consumes |
|---|---|---|---|
| magnum-api | magnum.cmd.api:main (werkzeug, magnum/cmd/api.py:58) or magnum/wsgi/api.py under uWSGI | REST API, validation, policies; in the magnum-api binary, database access goes through the conductor (versioned-object indirection, magnum/cmd/api.py:65), under uWSGI it is direct | HTTP :9511 |
| magnum-conductor | magnum.cmd.conductor:main (magnum/cmd/conductor.py:44) | RPC handlers, driver calls, certificates, periodic status/health/heartbeat (parent process only) | AMQP topic magnum-conductor |
| magnum-db-manage | magnum.cmd.db_manage:main | Alembic migrations | — |
| magnum-driver-manage | magnum.cmd.driver_manage:main | list installed drivers | — |
| magnum-status | magnum.cmd.status:main | upgrade checks | — |
External dependencies
| System | Protocol | Library | Configuration | Usage |
|---|---|---|---|---|
| MariaDB / MySQL | SQL | oslo.db, SQLAlchemy 2, Alembic | [database]/connection | 7 tables, no foreign keys |
| RabbitMQ | AMQP | oslo.messaging | [DEFAULT]/transport_url, [conductor]/topic | API→conductor RPC, CADF notifications |
| Keystone | REST | keystonemiddleware, keystoneauth, openstacksdk | [keystone_authtoken], [keystone_auth] | token validation, catalogue, projects |
| Glance, Nova, Neutron | REST | openstacksdk | [glance], [nova], [neutron] (region_name, endpoint_type) | request validation (images, flavors, keypairs, networks) |
| Barbican | REST | openstacksdk (service credentials) | [certificates]/cert_manager_type = barbican (default; x509keypair, local) | cluster CAs and client certificates |
| Kubernetes API of each cluster | HTTPS mTLS | requests | [kubernetes]/health_polling_interval | health status |
| Cluster driver | Python API | stevedore | [drivers]/* | builds the clusters; see 08 |
Files
| File | Content |
|---|---|
| 01-rest-api_stable-2026.2.md | 38 routes: functional and technical sheets, lifecycles |
| 02-errors_stable-2026.2.md | exception → HTTP translation, catalogue, asynchronous errors, logs |
| 03-interactions_stable-2026.2.md | RabbitMQ (RPC, notifications, frame), database, outbound REST, certificates |
| 04-scenarios_stable-2026.2.md | create, resize, upgrade, delete, kubeconfig, health |
| 05-async-processing_stable-2026.2.md | conductor RPC handlers and periodic tasks |
| 06-change-history_stable-2026.2.md | the 2026.2 cycle: Heat and trusts removed, openstacksdk, microversions 1.13/1.14, hidden templates, driver field |
07-rewrite-pack_stable-2026.2.md + [_rewrite/](_rewrite/rewrite-pack-index_stable-2026.2.md) | rewrite pack for openkeel-magnum |
| 08-driver-magnum-cluster-api_stable-2026.2.md | the vexxhost Cluster API driver v0.39.0: CAPI objects, field and label mapping, status derivation, credentials |
| _verification_stable-2026.2.md | reference check: each file:line and its enclosing function |
Key figures
- 38 (method, path) routes, 43 handlers, 15 microversioned handlers, microversions 1.1–1.14.
- 19 RPC methods received by the conductor (12 business, 3 indirection, 1 ping, 3 federation stubs); 3 periodic tasks; 0 notification listeners; 3 CADF event types emitted.
- 81 exception classes, about 20 of them never raised by core.
- 7 tables, Alembic head
b3e1cf4a2d5e; 66 policy rules; 0 drivers in-tree. - Rewrite pack: 532 HTTP exchanges from 456 API tests, 23 WSME types as JSON Schema, migrated MariaDB schema with 9 differences from the models.
Points of attention
- No driver in the box. Without an out-of-tree driver every cluster create returns 400
ClusterTypeNotSupported("none (no cluster drivers are loaded)"), andupdate_cluster_statusis a no-op in the base driver (magnum/drivers/common/driver.py:199). - Fire-and-forget operations.
- Cluster create, update, resize and delete and nodegroup operations are RPC casts answered with 202/204. Refusals and errors raised in the conductor before the database insert are never reported to the client.
- A GET just after a create can return 404.
- The quota check is not atomic with the insert (
magnum/api/controllers/v1/cluster.py:484).
- Upgrade is synchronous (RPC call,
magnum/conductor/api.py:84): a slow driver gives a 500 on timeout while the upgrade goes on. - Federation is a stub:
POST /v1/federationsreturns 202 with a UUID that never exists (magnum/conductor/handlers/federation_conductor.py:25). - 500 on CoreOS images:
_coreos_deprecation_noteis not defined (magnum/api/controllers/v1/cluster_template.py:462). - Microversion 1.14 not enforced:
node_labels/node_taintsare accepted from 1.9. - API validation and conductor may pick different drivers: the API checks the
(server_type, os, coe)tuple, the conductor loads the template's named driver (magnum/api/validation.py:51,magnum/drivers/common/driver.py:193). - Two database access modes depending on how magnum-api is started (binary → via conductor RPC; uWSGI → direct) (
magnum/cmd/api.py:65,magnum/wsgi/api.py:37). - Certificates:
- the etcd and front-proxy CAs are never deleted, and CA rotation leaves the old certificates in place (
magnum/conductor/handlers/common/cert_manager.py:240); - with
x509keypair, the encrypted keys sit next to their passphrases in the database; - the certificate cache directory is not refreshed after a rotation [inferred].
- the etcd and front-proxy CAs are never deleted, and CA rotation leaves the old certificates in place (
- No coordination between conductors: every host runs every periodic task on every cluster. The deletion cascade can race (
magnum/service/periodic.py:86). Health HTTP calls have no timeout (magnum/conductor/k8s_api.py:44). - Status codes that surprise:
NodeGroupInvalidInputinput errors are 409,KeyPairNotFoundis 404 while other missing dependencies are 400, and quotaPATCHreturns 202. - Client compatibility: microversion
latest(used by the auto-healer) removesstack_id(1.13), which gophercloud still parses (07 § 4). - Upgrade from 2026.1 (06 § 21–22, § 31): clusters built by the Heat driver become unmanageable; the trustee users stay in Keystone; service credentials must be in
[keystone_auth]. - Request bodies logged at DEBUG, including CSRs (
magnum/api/controllers/v1/__init__.py:241). - Driver-side (08 § 8, 08 § 11): with magnum-cluster-api,
PATCH /v1/clusters/{id}with a newnode_countputs the cluster in **UPDATE_FAILED**, because the driver'supdate_clusterraisesNotImplementedError(magnum-cluster-api:magnum_cluster_api/driver.py:329). Resizing must useactions/resize. The driver never sets*_FAILED, so a cluster stuck in Cluster API stays*_IN_PROGRESSforever. A missingkube_tagand nodegroup deletion after the MachineDeployment is gone are suspected failure cases [inferred in 08].
Blind spots / [inferred]
- No running Magnum was observed. Behaviour that depends on oslo.messaging, oslo.db or WSME internals (for example WSME's handling of unknown attributes) comes from reading the code and the API test exchanges.
- The magnum-cluster-api driver was read, not run. Its runtime behaviour against real CAPI/CAPO controllers is [inferred] where 08 says so.
- The other Cluster API driver,
magnum-capi-helm, andmagnum-tempest-pluginwere not analysed. - Nodegroup
*_COMPLETEtransitions and the removal of deleted nodegroups belong to the driver (08 § 5).
Source: reverse-spec-magnum/00-summary_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.