Reverse-specification of octavia — branch stable/2026.2
- Repository: https://opendev.org/openstack/octavia (local clone
../octavia) — specified branch:stable/2026.2@2900ed67cac2(19.0.0-19-g2900ed67, "Delete the VIP port when a load balancer creation fails") — analysed on: 2026-11-01 - Scope, as agreed: the REST API process in depth (routes, types, validation, errors, policies, DB, provider seam, status and statistics return path, what it needs from Neutron and Keystone) and the rewrite pack (step 8). OpenKeel will serve this API from Go behind the Neutron endpoint, with
openkeel-ovn-octavia-provideras its only back end; Python Octavia will not run. The amphora driver and what it brings are out of depth (05 § 3). The change history (step 7) was not requested.
| File | Content |
|---|---|
| 01-rest-api_stable-2026.2.md | pipeline, path families, route table, cross-cutting rules, sheets per resource, field tables, policies and RBAC modes, lifecycle |
| 02-errors_stable-2026.2.md | the three error bodies, translation, catalogue of exceptions with raise sites, provider and asynchronous errors, log messages |
| 03-interactions_stable-2026.2.md | database and locks, the provider seam (calls, conversion, status, statistics, get), Neutron, Keystone, Barbican, RabbitMQ |
| 04-scenarios_stable-2026.2.md | LB create, graph create, member batch, cascade delete, failed provider, statistics |
| 05-async-processing_stable-2026.2.md | driver agent; short description of what is out of depth |
| 07-rewrite-pack_stable-2026.2.md | contents of _rewrite/, conformance format and replay proof, seam mapping to the Go provider, DB strategy, gaps, checklist |
| _verification_stable-2026.2.md | output of the reference checker |
_inventory/, _rewrite/ | raw inventory; machine-readable contracts and conformance data (index: _rewrite/rewrite-pack-index_stable-2026.2.md) |
Overview
Octavia's API is a load-balancing control plane with almost no behaviour of its own: it validates a request, records the desired objects in SQL with a PENDING_* status while holding a row lock on the load balancer, and calls a provider driver in-process. It does not move an object out of PENDING_* itself: the provider reports back through Unix-socket status messages handled by a separate process (octavia-driver-agent), which also receives statistics and answers object reads. Network facts come from Neutron, with the caller's token by default. In this codebase the default provider is the amphora driver with its worker, health manager and VMs; none of them applies to OpenKeel, where the load balancers become OVN rows.
Architecture
flowchart LR client[openstack CLI, Heat, Magnum, cloud-provider-openstack, Skyline] -->|HTTPS /v2, /v2.0| api[octavia-api: Pecan + WSME] api -->|SQL, FOR UPDATE| db[(MariaDB)] api -->|token check| ks[Keystone] api -->|REST, user token| neutron[Neutron] api -->|REST| barbican[Barbican: certificates] api -->|in-process call: ProviderDriver| drv[provider driver] drv --> ovn[(OVN NB: OVN provider)] agent[octavia-driver-agent] -->|SQL| db drv2[provider agent or helper] -->|UDS status, stats, get| agent amp[amphora driver, worker, health manager]:::out -.->|out of depth| db api -.->|RPC cast, amphora routes| amp classDef out stroke-dasharray: 4 4;
Processes
| Process | Entry point | Role | Listens to | In OpenKeel |
|---|---|---|---|---|
octavia-api | octavia/cmd/api.py, octavia/api/app.py:63 | REST API (port 9876) | HTTP | Go rewrite, this spec |
octavia-driver-agent | octavia/cmd/driver_agent.py | status, statistics and get sockets; provider agents | /var/run/octavia/{status,stats,get}.sock | Go rewrite of the sockets (05 § 1) |
octavia-db-manage | octavia/db/migration/cli.py | Alembic (95 revisions) | CLI | replaced by the migrated DDL |
octavia-worker, octavia-health-manager, octavia-housekeeping, amphora-agent, prometheus-proxy… | pyproject.toml [project.scripts] | amphora driver | RabbitMQ, UDP heartbeats, timers | not ported, except the purge of DELETED load balancers (05 § 3) |
External dependencies
| System | Protocol | Library | Configuration | Usage |
|---|---|---|---|---|
| MariaDB/MySQL | SQL | SQLAlchemy, oslo.db | [database] connection | 39 model tables (41 migrated with alembic_version, spares_pool) |
| Keystone | HTTPS | keystonemiddleware, keystoneauth | [keystone_authtoken], [service_auth], [neutron] | token check; service sessions |
| Neutron | HTTPS | openstacksdk | [neutron], [networking] | VIP and member validation, VIP port for providers that do not make it |
| Barbican | HTTPS | python-barbicanclient/castellan | [certificates] cert_manager | TLS refs validation and reading (not needed once the OVN provider refuses TLS, § Points of attention) |
| RabbitMQ | AMQP | oslo.messaging | transport_url | only amphora routes and amphora provider; no notification from the API |
Key figures
- Routes: 297 entries: 75 canonical resource operations (69 under four prefixes, 6 amphora under two) + 9 discovery entries (01 § 1.2); 79 canonical in all.
- Conformance: 991 functional tests run (990 with exchanges, 1 skipped by the project), 8 691 recorded exchanges; replay from data only on the original code: 8 683 identical (8 679 exact + 4 order-insensitive), 8 different, all explained; 3 831 exchanges carry the provider calls they caused, 3 827 of them replayed identical (07 § 7).
- Seam vectors: 40 status/stats/get cases, 40/40 stable on re-run.
- Policies: 97 default rules (81 operation rules); matrix of 81 rules × 9 personas × 5 modes.
- Database: 39 tables in the models, 27 differences with the migrated schema (07 § 5).
- Errors: 81 exception classes in
octavia/common/exceptions.py, 52 reachable from the API scope.
Points of attention
- Two validators give two bodies, and Pecan a third:
{"faultcode","faultstring","debuginfo"};{"code","title","description"}(with the oddtitle: "Bad Request"on a 404 from_lookup); and plain text (healthcheck) (02 § 1). gophercloud and openstacksdk readfaultstring. - All resources exist under four prefixes (01 § 1.2), and
.xmlanswers XML. - **The default policy ignores
load-balancer_*roles**; deployments that use them need a policy file orenforce_new_defaults=False(01 § 6). - The LB row lock is held across the provider call: the Go provider's driver API must answer quickly, and it must not call back (01 § 3.4).
- **A provider that never reports leaves objects
PENDING_*for ever**, and everything under the LB immutable: the API has no timeout, the amphora flow's revert does that (03 § 2.3). - **Quota counters decrement only on a
DELETEDstatus message** (01 § 4.8). - The VIP port has two owners: the status path deletes it on
DELETEDonly ifoctavia_owned; the OVN provider does not set that flag and deletes its own port, while a failed creation is cleaned up by the API with its own Neutron credentials (03 § 2.3, 07 § 3). - OVN provider support is narrower than the API: TLS, L7, HM types, algorithms and failover come back as 501 after full API validation, with the provider's text (07 § 3).
- 500s to fix deliberately: a body without its root object, a JSON array, unknown flavor profile,
listener_idof a missing listener (01 § 3.1). - **
listener.insert_headersis a Python pickle** in the database, unreadable from Go (07 § 5). - Message texts contain Python artefacts: list reprs, dictionary reprs, set order. Clients that match them are unlikely [inferred]; the replay normalises them.
Blind spots / [inferred]
- No real Neutron, Barbican or Keystone was exercised: everything runs with
noauth/testing, the noop provider, noop network driver and a mock certificate manager. keystonemiddleware's 401 and token handling come from the code only. - The functional tests use SQLite; MariaDB-specific behaviour (deadlocks,
SERIALIZABLEflavor delete,SELECT FOR UPDATEcontention) comes from reading the code. get_network_ip_availability,allocate_vipwere read inoctavia/network/drivers/neutron/but executed only as their noop twins.- The provider driver code of octavia-lib (3.12.0 in the venv) and WSME (0.13.0), Pecan (1.8.0) were read without line references: they are not in the workspace.
- Statements marked [inferred] were deduced without a complete trace or test.
Source: reverse-spec-octavia/00-summary_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.