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

Reverse-spec · Clients

python-octaviaclient — Summary

Reverse-specification of python-octaviaclient — branch stable/2026.2

Branch stable/2026.2 @ b37975ec8f2d (tag 3.15.0 + 2 commits) — repository https://opendev.org/openstack/python-octaviaclient — analysed on 2026-11-01

  • Scope: all non-test code of the repository: the OSC plugin (octaviaclient/osc), and the Python API its commands use (octaviaclient/api). The change history (step 7) was not requested.
  • Dependencies read at fixed versions, from a venv: osc-lib 4.7.0, cliff 4.16.0, python-openstackclient 10.3.1, openstacksdk 4.20.0, keystoneauth1 5.17.0, Python 3.13. They are cited with the prefixes osc-lib:, cliff:, openstackclient:, keystoneauth: and requests:.
  • Service read for comparison, not run: Octavia stable/2026.2 @ 2900ed67cac2, cited as octavia:, and its report reverse-spec-octavia/.
  • References are file:line from the repository root. [observed]: seen by running the real shell against the local stub of 07. [inferred]: not followed to the end.
  • The stub is not a service. An [observed] behaviour says how the client reacts to a given answer. It says nothing about what a real Octavia answers, and nothing here was run against one.

Files of this specification

FileContent
01-cli-commands_stable-2026.2.mdshared mechanics, functional description per family, the 82 commands, and the wire effect of each option
02-errors_stable-2026.2.mdexit codes, HTTP error translation, client-side messages, and the 16 defects reproduced or read
03-interactions_stable-2026.2.mdKeystone, Octavia, Neutron; headers, bodies, query strings, pagination
04-scenarios_stable-2026.2.md5 scenarios with sequence diagrams and diagnostics
05-async-processing_stable-2026.2.mdno background processing; the two client-side loops
07-rewrite-pack_stable-2026.2.mdclient contract: what the CLI requires from a load-balancer service, test data, proof and limits
_verification_stable-2026.2.mdoutput of the reference checker

File 06 (change history) is absent because it was not requested.

Overview

python-octaviaclient is a plugin of the openstack command. It adds 82 loadbalancer … commands that drive the Octavia REST API. Each invocation is one short-lived process:

  1. python-openstackclient loads the plugin through entry points (setup.cfg:30-31);
  2. it authenticates against Keystone;
  3. the command resolves names to IDs with list calls;
  4. it sends its REST call through OctaviaAPI, a thin wrapper on osc_lib.api.api.BaseAPI (octaviaclient/api/v2/octavia.py:65);
  5. with --wait, it polls a status field;
  6. cliff prints the result.

It has no database, message bus, cache, server or background process. There is no version discovery and no microversion: the endpoint comes from the catalog and /v2.0 is appended (octaviaclient/api/v2/octavia.py:104-106).

Architecture

flowchart LR
  user[User or script] -->|argv, env| cli[openstack process]
  cfg[clouds.yaml, OS_* variables] --> cli
  cli --> plugin[octaviaclient.osc.v2 commands]
  plugin --> api[OctaviaAPI on osc-lib BaseAPI]
  plugin --> sdk[openstacksdk network proxy]
  plugin --> ksc[python-keystoneclient]
  api --> ksa[keystoneauth1 session]
  sdk --> ksa
  ksc --> ksa
  ksa -->|HTTPS, password, token, catalog| ks[Keystone]
  ksa -->|HTTPS, X-Auth-Token, /v2.0/lbaas and /v2.0/octavia| oct[Octavia]
  ksa -->|HTTPS, name to ID lookups| neu[Neutron]

Processes

ProcessEntry pointRoleListens to / consumes
openstack (from python-openstackclient)entry points openstack.cli.extension = load_balancer and openstack.load_balancer.v2 (setup.cfg:29-33)runs one commandargv, environment; listens on nothing

The package has no legacy CLI and no console script of its own: setup.cfg:29-115 declares entry points for OSC only, and no console_scripts. No separate shell exists to list.

External dependencies

SystemProtocolLibraryConfigurationUsage
KeystoneHTTPS RESTkeystoneauth1--os-auth-url, clouds.yamltoken, service catalog
KeystoneHTTPS RESTpython-keystoneclient, through client_manager.identitycatalogproject name to ID (octaviaclient/osc/v2/utils.py:172-179)
OctaviaHTTPS RESTOctaviaAPI (octaviaclient/api/v2/octavia.py:65)catalog, type load-balancer (octaviaclient/osc/plugin.py:32-36)all commands
NeutronHTTPS RESTopenstacksdkcatalog, type networksubnet, port, network, QoS policy, security group lookups (octaviaclient/osc/v2/utils.py:270-289)

Key figures

ItemCount
Commands82 in 14 families: 38 without table output, 29 single, 15 list; 491 arguments
Methods of OctaviaAPI73, one per route; all 73 routes observed on the wire
Commands sending at least one request to the stub72 of 82 with no optional argument; 82 of 82 with options. The other 10 are unset commands, which send no service request when no option is given
Wire runs82 per mode (404, {}, typed) and 475 in the option sweep, 1,275 requests in total
Exception classes defined by the package1 (octaviaclient/api/exceptions.py:15)
Unit tests421 pass, 287 vectors, 82 of 82 classes covered, 2 identical runs
Defects16 in 02 § 5: 14 reproduced on the stub (for 2 of them, one branch was only read), 1 reproduced on the client side with the service part read, 1 read only

Points of attention

  1. A paginated list loses its filter [observed]: the client replaces all query parameters with those of the next link (octaviaclient/api/v2/octavia.py:97-98), and Octavia's link carries only limit, sort and marker (octavia:octavia/api/common/pagination.py:151-172). A filter that fills the first page (1,000 items by default, octavia:octavia/common/constants.py:755) then shows unfiltered items from page 2 onwards, with exit 0. The two sides were read and the client reproduced on the stub; they were never run together.
  2. 13 commands need Neutron in the catalog, even when they never call it [observed]: loadbalancer list stops with Service 'network' is disabled… when no network service is listed, because attribute maps touch client_manager.sdk_connection.network when they are built (octaviaclient/osc/v2/utils.py:273, octaviaclient/osc/v2/utils.py:456). OpenKeel must register a network endpoint.
  3. **--wait has no timeout when waiting for ACTIVE [observed]**: wait_for_status loops until active or error (osc-lib:osc_lib/utils/__init__.py:805).
  4. A single-resource response must have its wrapper as the first JSON key [observed]: BaseAPI.find takes list(ret.keys())[0] (osc-lib:osc_lib/api/api.py:409). This matters for a Go service whose encoder sorts or reorders keys.
  5. Malformed responses and input give raw Python messages [observed]: 'NoneType' object has no attribute 'status_code', 'Response' object is not subscriptable, not enough values to unpack. See 02 § 5.
  6. **Numbers may arrive as strings, booleans as True/False [observed]**: connection_limit is a JSON string (octaviaclient/osc/v2/utils.py:262), and query booleans are admin_state_up=True, cascade=True. A strict Go decoder would reject these.
  7. **loadbalancer quota defaults show calls a route that does not exist as such**: GET /lbaas/quotas/defaults (octaviaclient/api/constants.py:61) lands on GET /quotas/{project_id} in Octavia (octavia:octavia/api/v2/controllers/quotas.py:37), so a non-admin should get 403 [inferred].
  8. Deprecated foundations: BaseAPI, wait_for_status, wait_for_delete and ClientCache are marked deprecated in osc-lib (osc-lib:osc_lib/api/api.py:69, osc-lib:osc_lib/utils/__init__.py:799, osc-lib:osc_lib/utils/__init__.py:747, osc-lib:osc_lib/clientmanager.py:41), and the package depends on all of them.
  9. Unit tests cannot catch these: the commands use a mocked API (octaviaclient/tests/unit/osc/v2/test_load_balancer.py:36), and the one port check that is dead is tested with a key the code never produces (octaviaclient/tests/unit/osc/v2/test_validations.py:116).
  10. **No command returns a value from command.Command**: the defect found in python-openstackclient does not occur here. An AST walk of the 38 command.Command classes found no return <value>, and all of them exit 0 on the typed stub [observed].

Blind spots / [inferred]

  • No real service was contacted. There are no functional tests: octaviaclient/tests/functional/base.py:45 holds a helper class and octaviaclient/tests/functional/osc/v2/ is empty. Compatibility with a real Octavia rests on reading its code and its OpenAPI, not on running them.
  • The stub answers what it is told. Its shaped responses are built from the client's own column lists, so an exit 0 in typed mode proves that requests are well formed for this stub and that the client copes with the answer.
  • **Multi-page lookups, real --wait transitions and real deletion** were simulated, not observed on a service.
  • The wait timeout of 300 s for deletion was read (osc-lib:osc_lib/utils/__init__.py:727), not waited for.
  • Output formatting by cliff (table, JSON, YAML, CSV, value) was not specified command by command. Column lists are in octaviaclient/osc/v2/constants.py:15.
  • Authentication variants other than password were not run; they belong to python-openstackclient and keystoneauth1.
  • **octaviaclient/hacking/checks.py:1** is a flake8 plugin for developers, not run-time code; it was not specified.
  • **requests_mock API tests** (octaviaclient/tests/unit/api/test_octavia.py:1) pass and are counted in the 421, but they give no vectors, since the capture records check_parser tests only.

Source: reverse-spec-python-octaviaclient/00-summary_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.