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

Reverse-spec · Clients

python-neutronclient — Summary

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

Branch stable/2026.2 @ 596a9d99b188 (14.0.0 + 2 maintenance commits) — repository https://opendev.org/openstack/python-neutronclient — analysed on 2026-11-01

  • Scope: the whole repository (package neutronclient): the OSC plugin, the Python client class, the leftovers of the removed CLI. The change history (step 7) was not requested, so there is no 06 file.
  • Dependencies read at fixed versions, from the venv: osc-lib 4.7.0, cliff 4.16.0, openstacksdk 4.20.0, keystoneauth1 5.17.0, python-keystoneclient 6.0.0, python-openstackclient 10.3.1. Cited with the prefixes osc-lib:, cliff:, openstacksdk:, keystoneauth1:, openstackclient:. Other projects are cited with their clone name; their commits are in 07 § 4.
  • References are file:line from the repository root. [observed] means seen by running the real openstack command or the real class against the local stub. [inferred] marks a statement not followed to the end.
  • The stub is not Neutron. No real service, lab or cloud was contacted. Every [observed] result shows how the client reacts to canned answers, and says nothing about what a real service sends.

Files of this specification

FileContent
01-cli-commands_stable-2026.2.mdplugin loading, the 34 commands with arguments, routes and bodies, and the Python API the commands use
02-errors_stable-2026.2.mdexit codes, the exception catalogue, the HTTP translation, the 23 messages of the commands, and the defects reproduced
03-interactions_stable-2026.2.mdKeystone and Neutron through two client stacks, headers, URL building, retries
04-scenarios_stable-2026.2.md5 scenarios with sequence diagrams and diagnostics
05-async-processing_stable-2026.2.mdnone; only client-side pagination and retry loops
07-rewrite-pack_stable-2026.2.mdclient contract: what the plugin and the library's users require from a Neutron service
_verification_stable-2026.2.mdoutput of the reference checker

Overview

The package now provides three different things:

  1. An OSC plugin with 34 commands. All 34 load in the real shell [observed]. 27 (sfc *) use openstacksdk and do not touch the class of this package. 7 (network log *, network loggable resources list, network onboard subnets) use it.
  2. **A Python library, neutronclient.v2_0.client.Client**, with 372 public methods and 168 path constants (neutronclient/v2_0/client.py:495), plus the exception module neutronclient/common/exceptions.py:42. It logs a deprecation warning on every instantiation (neutronclient/v2_0/client.py:253). Nova, Heat, Manila, Zun, ec2-api, Skyline and heat-tempest-plugin import it.
  3. **The remains of the neutron CLI**: 63 files and 8,693 lines under neutronclient/neutron/. No script starts them: setup.cfg has no console_scripts, so there is no legacy shell process. The package still imports them: the base module neutronclient/neutron/v2_0/__init__.py:53 has the helper find_resourceid_by_name_or_id, used by Nova, Heat and Zun.

**What IGNORED_MODULES does here: nothing, at this commit.** openstackclient:openstackclient/shell.py:34 lists neutronclient.osc.v2.fwaas, .taas, .networking_bgpvpn, .dynamic_routing and .vpnaas, but setup.cfg declares none of them: the only groups are openstack.cli.extension and openstack.neutronclient.v2, whose 34 entry points are in neutronclient/osc/v2/logging, sfc and subnet_onboard. The directory neutronclient/osc/v2/fwaas keeps only neutronclient/osc/v2/fwaas/constants.py:18, imported by the log command. The firewall, BGP VPN, dynamic routing, TaaS and VPN commands exist, and come from OSC itself (openstackclient:pyproject.toml:596). openstack command list --group neutronclient shows exactly the 34 [observed].

Architecture

flowchart LR
  user[User or script] -->|argv| osc[openstack process]
  osc -->|entry point openstack.cli.extension| plugin[neutronclient.osc.plugin]
  plugin -->|27 sfc commands| sdk[openstacksdk Proxy]
  plugin -->|7 log and onboard commands| nc[neutronclient.v2_0.client.Client]
  plugin -->|--project only| ksc[python-keystoneclient]
  sdk --> ksa[keystoneauth1 session]
  nc --> ksa
  ksc --> ksa
  ksa -->|HTTPS, X-Auth-Token| neutron[Neutron /v2.0]
  ksa -->|HTTPS| ks[Keystone]
  svc[Nova, Heat, Manila, Zun, ec2-api, Skyline] -->|import| nc

Processes

ProcessEntry pointRoleListens to / consumes
openstack (python-openstackclient)setup.cfg:32, neutronclient/osc/plugin.py:38runs one plugin commandargv, environment; listens on nothing

There is no neutron script, daemon, agent or server in this repository.

External dependencies

SystemProtocolLibraryConfigurationUsage
NeutronHTTPS RESTClient → keystoneauth1; openstacksdkKeystone catalog, type networkall commands
KeystoneHTTPS RESTkeystoneauth1; python-keystoneclient for --project--os-auth-url, clouds.yamltoken, catalog; project lookup in network log create
Keystone v2 /tokensHTTPS RESTrequests directly, class HTTPClientauth_url, only without a sessionlegacy password path, see 02 § 4

Key figures

ItemCount
Commands34, all loaded; 94 arguments, 33 required
Client stack27 openstacksdk; 7 neutronclient, of which 2 can also call python-keystoneclient
Commands reaching a request on the stub34 of 34 in each of the 3 modes
Commands exiting 0404 mode 0; {} mode 22; rich mode 34; rich with all options 34
Routes observed for the commands48 (method, route, query keys)
Public methods of Client372; 123 called by name in other projects [inferred]; 94 whose path has no match in neutron-lib or neutron definitions
Exception classes36 in the inventory; 0 specific to OSC commands
Unit tests154 of 154 pass, 90 vectors, same call sequences in two runs
Classes without a vector0 of 34
Commands deriving from command.Command that return a value0 of 15, by AST

Points of attention

  1. **sfc port pair group set crashes on an unknown group [observed]**: it alone omits ignore_missing=False (neutronclient/osc/v2/sfc/sfc_port_pair_group.py:197), and prints 'NoneType' object is not subscriptable.
  2. The client-side cycle check misses cycles longer than 2 [observed]: a:b b:c c:a is sent to the server and exits 0 (neutronclient/osc/v2/sfc/sfc_service_graph.py:233).
  3. **network log list reuses or loses the event [observed]**: with an empty event, the first row crashes and a later row shows the event of the previous row (neutronclient/osc/v2/logging/network_log.py:228).
  4. **A 200 {} from the service gives a raw Python error [observed]**: tuple indices must be integers or slices, not str on network log list (neutronclient/v2_0/client.py:403). A compatible service must always send the collection key.
  5. **An error without detail is displayed as a Python dict [observed]**: {'type': 'BadRequest', 'message': 'm'}, and the typed exception is lost (neutronclient/v2_0/client.py:67). A compatible service must send type, message and detail.
  6. **The binding hard-codes /v2.0 [observed]**: a catalog URL ending in /v2.0 gives /network/v2.0/v2.0/log/logs on the 7 binding commands, while SDK commands cope (neutronclient/v2_0/client.py:260, openstacksdk:openstack/config/cloud_region.py:1134).
  7. The docstring's usage fails against Keystone v3 [observed on the stub]: without a session, the class posts Keystone v2 credentials to {auth_url}/tokens (neutronclient/client.py:221). Every project found here passes a session.
  8. Two error formats: a 404 reads stub: not found on binding commands and NotFoundException: 404: Client Error for url: …, stub: not found on SDK commands [observed].
  9. Every binding command prints a deprecation warning on stderr [observed] (neutronclient/v2_0/client.py:253). Scripts that treat stderr output as failure will trip on it.
  10. Unit tests cannot catch these: they mock both clients (neutronclient/tests/unit/osc/v2/fakes.py:27), which is why items 1 to 5 pass them.
  11. The release note overstates the removal: it says all CLI code was removed (releasenotes/notes/remove-cli-code-53969e9aa927e530.yaml:10), and 63 files remain.
  12. Probably dead routes in the library: 47 of the 63 /lb and /lbaas methods, and all 16 of /qos-queues, /network-gateways and /gateway-devices, have no match in neutron-lib or neutron definitions [inferred, by text search]. See the surface.

Blind spots / [inferred]

  • No real Neutron was contacted, so nothing here proves that a service accepts these requests or sends these fields. Bodies such as "symmetric": "true" were seen leaving the client; acceptance by a server was not tested.
  • networking-sfc is not cloned here, so the server side of the 27 sfc commands was not read. neutron-lib has sfc.py and flowclassifier.py definitions, but /sfc/service_graphs has no text match in them.
  • The rich stub answers are hand-written from the commands' own field lists. A field that the real service sends and the stub omits was not exercised.
  • **The called_by column is a name search**: another client with a method of the same name gives a false positive, Heat especially. No consumer was run.
  • **Legacy modules under neutronclient/neutron/v2_0** were imported (94 modules of the package, 0 failures) and not exercised, apart from find_resourceid_by_name_or_id [observed].
  • **neutronclient.extension entry points** (neutronclient/common/extension.py:22): no package in the venv declares one, so extension loading ran empty.
  • **TLS, --insecure, client certificates and osprofiler headers** were read, not run. The stub is plain HTTP.
  • Output formatting by cliff was not specified command by command.
  • Language of the messages: translated with oslo.i18n; only English was seen.

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