Processing outside the API — octavia — branch stable/2026.2
Branch
stable/2026.2@2900ed67cac2— repository https://opendev.org/openstack/octavia — analysed on 2026-11-01
| Process | Trigger | Type | Purpose | Reads | Writes / emits | Defined at |
|---|---|---|---|---|---|---|
| octavia-driver-agent | status.sock | Unix stream socket, one fork per request | a provider reports statuses | message | load_balancer, listener, pool, member, health_monitor, l7policy, l7rule, quotas; VIP deallocation | octavia/api/drivers/driver_agent/driver_listener.py:49 |
| octavia-driver-agent | stats.sock | same | a provider reports listener statistics | message | listener_statistics via [controller_worker] statistics_drivers | octavia/api/drivers/driver_agent/driver_listener.py:73 |
| octavia-driver-agent | get.sock | same | a provider reads an object | all resource tables | nothing | octavia/api/drivers/driver_agent/driver_listener.py:97 |
| octavia-driver-agent | provider agents | child processes from entry points octavia.driver_agent.provider_agents | run the provider's own loops (OVN provider: OVSDB events, maintenance) | — | — | octavia/cmd/driver_agent.py:54-57 |
Everything else found by the inventory (28 triggers) is the amphora driver: § 3.
1. Driver agent
1.1 Sockets
- Framing:
<decimal length>\n<JSON of that length>, both ways; one request per connection (octavia/api/drivers/driver_agent/driver_listener.py:33-46,octavia/api/drivers/driver_agent/driver_listener.py:63-68). - Server:
ForkingMixIn+UnixStreamServer, a process per request (octavia/api/drivers/driver_agent/driver_listener.py:120-122). - Limits:
max_children = *_max_processes(50),timeout = *_request_timeout(5 s) (octavia/api/drivers/driver_agent/driver_listener.py:139-140). The socket files are removed at start and at stop (octavia/api/drivers/driver_agent/driver_listener.py:125-131). - Client side (provider): octavia-lib
DriverLibrary; default paths/var/run/octavia/{status,stats,get}.sock; send timeout 5 s, receive 30 s in the Go client (openkeel-ovn-octavia-provider:internal/driverlib/driverlib.go:123-124). - Receive failure: logged, connection dropped, no reply.
1.2 Status message
Trigger: update_loadbalancer_status of the driver library. Emitter: the provider. Purpose: move objects out of PENDING_*, publish operating statuses.
Order of processing is fixed: members, health monitors, pools, L7 rules, L7 policies, listeners, load balancers; unknown top-level keys are ignored (octavia/api/drivers/driver_agent/driver_updater.py:142-179). For each record (octavia/api/drivers/driver_agent/driver_updater.py:89-127):
prov_status == DELETED:- load balancer: if
vip.octavia_owned,deallocate_vipwith the service credentials (octavia/api/drivers/driver_agent/driver_updater.py:48-57); - quota decrement in its own locking transaction, unless already
DELETEDor row missing (octavia/api/drivers/driver_agent/driver_updater.py:59-87); - non-LB:
DELETErow and return; a load balancer row stays, statusDELETED.
- load balancer: if
- Otherwise
UPDATE … SET provisioning_status, operating_statusfor those present; a record with neither does nothing. - Any exception →
UpdateStatusError→ reply withstatus_code: 500and the identification; no rollback of earlier records.
Reply: {"status_code": 200} or the fault (values from octavia-lib DRVR_STATUS_CODE_OK/FAILED). Idempotency: repeating a message is harmless; a DELETED repeated on a LB finds the row already DELETED and skips the quota but calls deallocate_vip again. Concurrency: per-record transactions; two senders may interleave; last write wins. Cost: at least 1 transaction per record, 2-3 for a deletion. Vectors: _rewrite/cases-driver-seam_stable-2026.2.json.
1.3 Statistics message
Each listener record needs id, bytes_in, bytes_out, active_connections, total_connections, request_errors (octavia/api/drivers/driver_agent/driver_updater.py:204-217). stats_base.update_stats_via_driver(deltas=False) calls each driver of statistics_drivers (default stats_db) (octavia/statistics/stats_base.py:39-48, octavia/common/config.py:518): absolute values replace the row keyed on (listener, amphora); without amphora id the amphora_id column takes the listener id (octavia/db/repositories.py:1187-1209). The API read path knows this trick: active_connections of a row counts only if its amphora is ALLOCATED or amphora_id == listener_id (octavia/common/stats.py:42-53).
1.4 Get message
{"object": "loadbalancers"|"listeners"|"pools"|"members"|"healthmonitors"|"l7policies"|"l7rules", "id": "<uuid>"} → the provider object to_dict(recurse=True, render_unsets=True) (all keys present, unset as null), or {} when unknown, DELETED, or the object kind is unknown (octavia/api/drivers/driver_agent/driver_get.py:23-90). The OVN provider uses it for its members and pools.
2. API-side background
None: the API process has no periodic task and no consumer. Start-up: _init_drivers loads each enabled provider and removes those that fail (octavia/api/app.py:45-60).
3. Out of depth: the amphora driver and everything it brings
Not ported; listed so that nobody searches them in this spec.
| Part | What it is | Where |
|---|---|---|
| amphora provider driver | turns driver calls into RPC casts to the worker | octavia/api/drivers/amphora_driver/v2/driver.py |
| controller worker | taskflow flows building VMs, ports, certificates, haproxy configs; also sends the notifications octavia.* when [controller_worker] event_notifications | octavia/controller/worker/v2/, octavia/controller/worker/v2/tasks/notification_tasks.py |
amphora agent, haproxy-vrrp-check, amphora-health-checker, amphora-interface, prometheus-proxy | code inside the VM image | octavia/amphorae/, octavia/cmd/ |
| health manager | UDP heartbeats from amphorae, statuses, failover | octavia/controller/healthmanager/ |
| housekeeping | spare/certificate rotation, **DB purge of DELETED load balancers and amphorae** | octavia/controller/housekeeping/house_keeping.py:39, octavia/controller/housekeeping/house_keeping.py:66 |
| certificates, compute, volume, image drivers | Nova, Cinder, Glance | octavia/certificates/, octavia/compute/, octavia/volume/, octavia/image/ |
The only item with a visible effect on the API contract is the purge: DELETED LB rows are invisible through the API, so without a purge they only use space. The Go port should add a small periodic delete (load_balancer_expiry_age, default 604800 s) **[inferred from octavia/controller/housekeeping/house_keeping.py:66]**.
Source: reverse-spec-octavia/05-async-processing_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.