Reverse-specification of ovn-octavia-provider — branch stable/2026.2
Branch
stable/2026.2@c56940998594(11.0.0-2-gc569409) — repository https://opendev.org/openstack/ovn-octavia-provider — analysed on 2026-10-28
- Scope: the whole project (about 7,400 lines of Python outside tests): the Octavia provider driver, the request queue and helper, the provider agent (OVSDB events, maintenance tasks), the OVSDB layer, the Neutron/Octavia clients and the sync tools; plus a rewrite pack. No change history (step 7) was requested.
- References are
file:linerelative to the repository root.octavia:is Octaviastable/2026.2@2900ed67cac2,octavia-lib:is octavia-libstable/2026.2@a46b0ff4fa95,neutron:is Neutronstable/2026.2@eef1a0f7ee36. [inferred] marks a statement not followed to the end in the code.
Files of this specification
| File | Content |
|---|---|
| 01-driver-api_stable-2026.2.md | the provider-driver methods called by Octavia (instead of REST endpoints), the OVN NB row layout, lifecycles |
| 02-errors_stable-2026.2.md | exception → HTTP translation by Octavia, synchronous refusals, asynchronous ERROR statuses, retries, key logs |
| 03-interactions_stable-2026.2.md | OVSDB connections, tables and transactions; driver-agent sockets (status, get); Neutron and Octavia REST calls |
| 04-scenarios_stable-2026.2.md | 5 scenarios: LB creation, health monitor and failing member, VIP floating IP, router interface, cascade delete |
| 05-async-processing_stable-2026.2.md | the request queue, the three OVSDB events, the three maintenance tasks, the sync tool |
| 07-rewrite-pack_stable-2026.2.md | rewrite pack: OVN NB contract, vips algorithm with 57 replayed vectors, status derivation, client expectations, checklist |
| _verification_stable-2026.2.md | every reference with the function it points into |
Overview
ovn-octavia-provider lets Octavia create load balancers without amphora VMs: each Octavia load balancer becomes one or more rows of the OVN Northbound Load_Balancer table, which ovn-northd and ovn-controller turn into distributed DNAT flows on every chassis. Only L4 is supported (TCP, UDP, SCTP), with SOURCE_IP_PORT or SOURCE_IP hashing, TCP/UDP-CONNECT health checks and SOURCE_IP session persistence.
The code runs inside two Octavia processes:
- in octavia-api, the
ovnprovider driver validates each API call synchronously, creates the VIP port in Neutron, and queues the work for a helper thread that writes the OVN NB database and reports statuses to Octavia; - in octavia-driver-agent, the
ovnprovider agent watches OVN (router interfaces, floating IPs on VIP ports, health-check results in the SouthboundService_Monitortable) and runs repair tasks.
The provider has no database of its own: its state is stored in Load_Balancer.external_ids. It reads Octavia objects and reports statuses through the driver-agent Unix sockets, and calls Neutron for ports, subnets and floating IPs.
Architecture
flowchart LR
user[User / CLI] -->|HTTPS REST| api[octavia-api]
subgraph api_p[octavia-api process]
api --> drv[ovn provider driver] --> hq[request queue + helper thread]
end
subgraph agent_p[octavia-driver-agent process]
sock[status.sock / get.sock]
pa[ovn provider agent: events + maintenance + helper]
end
hq -->|OVSDB transact| nb[(OVN Northbound)]
pa -->|OVSDB transact / monitor + lock| nb
pa -->|OVSDB monitor + lock| sb[(OVN Southbound)]
hq -->|JSON over Unix socket| sock
pa -->|JSON over Unix socket| sock
sock -->|SQL| odb[(Octavia DB)]
drv -->|REST ports, subnets| neutron[Neutron]
hq -->|REST ports, subnets, floating IPs| neutron
pa -->|REST ports| neutron
nb --> northd[ovn-northd] --> sb --> ctl[ovn-controller on each chassis]
neutron -->|OVSDB| nbProcesses
| Process | Entry point | Role | Listens to / consumes |
|---|---|---|---|
| octavia-api (plugin) | octavia.api.drivers = ovn → ovn_octavia_provider/driver.py:40 (setup.cfg:32-33) | validate calls, create VIP ports, queue OVN work, report statuses | in-process queue (ovn_octavia_provider/helper.py:408) |
| octavia-driver-agent (plugin) | octavia.driver_agent.provider_agents = ovn → ovn_octavia_provider/agent.py:31 (setup.cfg:38-39) | OVSDB events, maintenance, queue | NB Logical_Router_Port, Logical_Switch_Port; SB Service_Monitor; timers |
octavia-ovn-db-sync-util | ovn_octavia_provider/cmd/octavia_ovn_db_sync_util.py:37 (setup.cfg:35-36) | repair OVN from the Octavia DB | — |
neutron-ovn-db-sync-util plugin octavia_ovn_sync | ovn_octavia_provider/ovn/db_sync.py:30 (setup.cfg:44-45) | same, from Neutron's sync tool | — |
External dependencies
| System | Protocol | Library | Configuration | Usage |
|---|---|---|---|---|
| OVN Northbound | OVSDB JSON-RPC (TCP/SSL/Unix) | ovsdbapp, ovs | [ovn] ovn_nb_* | state store and data plane |
| OVN Southbound | OVSDB JSON-RPC | ovsdbapp | [ovn] ovn_sb_* | health-check results |
| Octavia driver agent | JSON over Unix sockets | octavia-lib DriverLibrary | octavia-lib defaults /var/run/octavia/*.sock | status updates, object reads |
| Neutron | REST | openstacksdk, keystoneauth1 | [neutron], [service_auth] | VIP and HM ports, subnets, floating IPs |
| Octavia API | REST | openstacksdk | [service_auth] | list LBs (sync only) |
Key figures
- 19 provider-driver methods implemented (15 Octavia calls, plus create-VIP-port, batch update, failover refusal and sync), L7/flavor/AZ left unimplemented (501).
- 20 request types handled by the helper thread (
ovn_octavia_provider/helper.py:70-92). - 3 OVSDB events, 3 periodic maintenance tasks (600 s, self-stopping), 1 on-demand sync.
- 3 exception classes defined (2 never raised); about 20 distinct synchronous refusal messages.
- 9 NB tables replicated, 4 written (
Load_Balancer,Load_Balancer_Health_Check,Logical_Switch/Logical_Routerload_balancercolumns, 2NATcolumns); 1 SB table monitored. - 13 Neutron REST operations, 2 driver-agent socket operations, 1 Octavia REST operation.
- Rewrite pack: 57
vipsvectors, 57/57 replayed.
Points of attention
- One driver instance per API call: Octavia instantiates the driver for every call, so each call opens an NB connection and starts a helper thread (
octavia:octavia/api/drivers/driver_factory.py:43,ovn_octavia_provider/helper.py:55-68). Requests of different calls run concurrently and unordered on the same rows, with no optimistic locking (03 § 1.3). - "Unsupported" is HTTP 501, not 400 (02 § 1).
- Unsupported session-persistence types give a 500: the error message formatting reads
session.typeon a dict (ovn_octavia_provider/driver.py:79-80). - **
pool_updatesilently ignores algorithm changes** (ovn_octavia_provider/driver.py:282-295), andselection_fields/affinity_timeoutare shared by every pool of the same protocol (ovn_octavia_provider/helper.py:2364-2366). The admin guide still says onlySOURCE_IP_PORTis supported (doc/source/admin/driver.rst:44). - **Stuck
PENDING_*statuses**: a handler that raises outside its owntrysends no status (ovn_octavia_provider/helper.py:434-437), and a failing status socket blocks the queue for up to ~15 minutes before giving up (ovn_octavia_provider/helper.py:448-451). - Members without a subnet get the VIP subnet, which is not stored in Octavia; such a member cannot be deleted if its address does not fit the VIP subnet any more (
ovn_octavia_provider/driver.py:440-460). - A disabled health monitor still probes (only the reported status changes,
ovn_octavia_provider/helper.py:3488-3490). - The OVSDB event lock only serialises event handling across agents; maintenance tasks run in every agent (
ovn_octavia_provider/maintenance.py:72). - Process-wide SSL settings for NB and SB (
ovn_octavia_provider/ovsdb/ovsdb_monitor.py:89-118). - **
lb_createfailure after the row was committed** reportsERRORbut leaves theLoad_Balancerrow (ovn_octavia_provider/helper.py:1732-1760).
Blind spots / [inferred]
- The Octavia side (API locking,
PENDING_*transitions, driver-agent processing) was read only at the points cited; its full behaviour is outside this spec. - The exact OVSDB wire encoding (mutate versus update) is chosen by the
ovsIDL and is shown reconstructed (03 § 1.4). - ovn-northd behaviour (how
vips,selection_fields,ip_port_mappingsand health checks become flows andService_Monitorrows) is not part of this repository. - The functional tests (
ovn_octavia_provider/tests/functional/) need a running OVN and were not run; no dynamic capture was made. openstacksdkfind_portrequest sequence is inferred from the library's general behaviour.ovn_octavia_provider/hacking/(flake8 checks) is development tooling and not described.
Source: reverse-spec-ovn-octavia-provider/00-summary_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.