OpenKeel: the sovereign French Cloud solution of the inherent group, with a European reach Discover inherent

Reverse-spec · Services

magnum — Summary

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

ProcessEntry pointRoleListens to / consumes
magnum-apimagnum.cmd.api:main (werkzeug, magnum/cmd/api.py:58) or magnum/wsgi/api.py under uWSGIREST 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 directHTTP :9511
magnum-conductormagnum.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-managemagnum.cmd.db_manage:mainAlembic migrations—
magnum-driver-managemagnum.cmd.driver_manage:mainlist installed drivers—
magnum-statusmagnum.cmd.status:mainupgrade checks—

External dependencies

SystemProtocolLibraryConfigurationUsage
MariaDB / MySQLSQLoslo.db, SQLAlchemy 2, Alembic[database]/connection7 tables, no foreign keys
RabbitMQAMQPoslo.messaging[DEFAULT]/transport_url, [conductor]/topicAPI→conductor RPC, CADF notifications
KeystoneRESTkeystonemiddleware, keystoneauth, openstacksdk[keystone_authtoken], [keystone_auth]token validation, catalogue, projects
Glance, Nova, NeutronRESTopenstacksdk[glance], [nova], [neutron] (region_name, endpoint_type)request validation (images, flavors, keypairs, networks)
BarbicanRESTopenstacksdk (service credentials)[certificates]/cert_manager_type = barbican (default; x509keypair, local)cluster CAs and client certificates
Kubernetes API of each clusterHTTPS mTLSrequests[kubernetes]/health_polling_intervalhealth status
Cluster driverPython APIstevedore[drivers]/*builds the clusters; see 08

Files

FileContent
01-rest-api_stable-2026.2.md38 routes: functional and technical sheets, lifecycles
02-errors_stable-2026.2.mdexception → HTTP translation, catalogue, asynchronous errors, logs
03-interactions_stable-2026.2.mdRabbitMQ (RPC, notifications, frame), database, outbound REST, certificates
04-scenarios_stable-2026.2.mdcreate, resize, upgrade, delete, kubeconfig, health
05-async-processing_stable-2026.2.mdconductor RPC handlers and periodic tasks
06-change-history_stable-2026.2.mdthe 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.mdthe vexxhost Cluster API driver v0.39.0: CAPI objects, field and label mapping, status derivation, credentials
_verification_stable-2026.2.mdreference 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

  1. No driver in the box. Without an out-of-tree driver every cluster create returns 400 ClusterTypeNotSupported ("none (no cluster drivers are loaded)"), and update_cluster_status is a no-op in the base driver (magnum/drivers/common/driver.py:199).
  2. 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).
  3. Upgrade is synchronous (RPC call, magnum/conductor/api.py:84): a slow driver gives a 500 on timeout while the upgrade goes on.
  4. Federation is a stub: POST /v1/federations returns 202 with a UUID that never exists (magnum/conductor/handlers/federation_conductor.py:25).
  5. 500 on CoreOS images: _coreos_deprecation_note is not defined (magnum/api/controllers/v1/cluster_template.py:462).
  6. Microversion 1.14 not enforced: node_labels/node_taints are accepted from 1.9.
  7. 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).
  8. 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).
  9. 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].
  10. 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).
  11. Status codes that surprise: NodeGroupInvalidInput input errors are 409, KeyPairNotFound is 404 while other missing dependencies are 400, and quota PATCH returns 202.
  12. Client compatibility: microversion latest (used by the auto-healer) removes stack_id (1.13), which gophercloud still parses (07 § 4).
  13. 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].
  14. Request bodies logged at DEBUG, including CSRs (magnum/api/controllers/v1/__init__.py:241).
  15. Driver-side (08 § 8, 08 § 11): with magnum-cluster-api, PATCH /v1/clusters/{id} with a new node_count puts the cluster in **UPDATE_FAILED**, because the driver's update_cluster raises NotImplementedError (magnum-cluster-api:magnum_cluster_api/driver.py:329). Resizing must use actions/resize. The driver never sets *_FAILED, so a cluster stuck in Cluster API stays *_IN_PROGRESS forever. A missing kube_tag and 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, and magnum-tempest-plugin were not analysed.
  • Nodegroup *_COMPLETE transitions 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.