Reverse-specification of python-masakariclient — branch stable/2026.2
Branch
stable/2026.2@073cd2cca082(8.9.0+ 2 commits) — repository https://opendev.org/openstack/python-masakariclient — analysed on 2026-11-01
- Scope: the whole repository, all 15 OSC commands. The change history was not requested, so there is no file 06.
- Dependencies read at fixed versions (the shared venv): openstacksdk 4.20.0, osc-lib 4.7.0, cliff 4.16.0, keystoneauth1 5.17.0, python-openstackclient 10.3.1. Cited with the prefixes
openstacksdk:,osc-lib:,cliff:,openstackclient:. The service is cited asmasakari:(commitae41528e1ebc, read only, not run). The package installed in the venv is byte-identical to the clone (diff -r, excluding__pycache__). - References are
file:linefrom the repository root. [observed] means seen by running the real CLI against a local stub. [inferred] means not followed to the end. Unmarked statements come from reading the code. - The stubs are not Masakari. What is observed says how the CLI behaves against a stub built to the shapes recorded in
reverse-spec-masakari. It says nothing about a real service, and no real service, lab or cloud was contacted.
Files of this specification
| File | Content |
|---|---|
| 01-cli-commands_stable-2026.2.md | shared mechanics, the 15 commands with arguments, requests and output columns, resource lifecycle as seen by the client |
| 02-errors_stable-2026.2.md | exit codes, the 10 messages of the project, reproduced failures, and the defects |
| 03-interactions_stable-2026.2.md | Keystone, discovery, microversions, requests sent to Masakari, sample frames |
| 04-scenarios_stable-2026.2.md | 5 sequence diagrams with error branches |
| 05-async-processing_stable-2026.2.md | none, and what the user must poll |
| 07-rewrite-pack_stable-2026.2.md | client contract: what a service must do for these commands, evidence and limits |
| _verification_stable-2026.2.md | output of the reference checker |
Overview
python-masakariclient is a thin plugin of the openstack command. It adds 15 commands that drive Masakari (instance high availability): failover segments, hosts in a segment, notifications, and VM moves of a notification. It holds no REST code: every call goes through the instance_ha proxy of openstacksdk (masakariclient/plugin.py:38, openstacksdk:openstack/instance_ha/v1/_proxy.py:28). The commands add name-to-UUID lookup, client-side argument checks, column selection and three microversion gates.
flowchart LR user[User or script] -->|argv| cli[openstack process] cli -->|entry points| plugin[masakariclient.plugin and osc.v1] plugin --> sdk[openstacksdk instance_ha Proxy] sdk --> ksa[keystoneauth1 session] ksa -->|HTTP POST /v3/auth/tokens| ks[Keystone] ksa -->|HTTP, X-Auth-Token, OpenStack-API-Version: instance-ha 1.3| m[Masakari API]
Processes
| Process | Entry point | Role | Listens to / consumes |
|---|---|---|---|
openstack (python-openstackclient) | setup.cfg:29 (openstack.cli.extension, ha), setup.cfg:32 (openstack.ha.v1) | loads the plugin and runs one command | argv; listens on nothing |
There is no legacy shell. setup.cfg declares no console_scripts, and releasenotes/notes/drop-the-legacy-client-1b25f27aa5525295.yaml:4 records that the masakari command was removed. README.rst:12 still announces it, along with a Python API: stale text.
The Python API is minimal. Nothing in the package wraps the service any more. The commands use three helpers of their own: get_uuid_by_name (masakariclient/common/utils.py:90), format_sort_filter_params (masakariclient/common/utils.py:58) and APIVersion (masakariclient/api_versions.py:23). No other local repository imports masakariclient: masakari-monitors and masakari-dashboard use openstacksdk directly (masakari-monitors:masakarimonitors/ha/masakari.py:46, masakari-dashboard:masakaridashboard/api/api.py:53).
External dependencies
| System | Protocol | Library | Configuration | Usage |
|---|---|---|---|---|
| Keystone | HTTP REST | keystoneauth1 | --os-auth-url, clouds.yaml, OS_* | token and catalog |
| Masakari | HTTP REST | openstacksdk | catalog type instance-ha or its alias ha; --os-ha-api-version (masakariclient/plugin.py:51) | every command |
Key figures
| Item | Count |
|---|---|
| Commands | 15 (segments 5, hosts 5, notifications 3, VM moves 2), 55 own arguments |
| Service operations used | 15 of the 19 in the Masakari table, plus GET /v1 for discovery; GET / and the 2 /v1/extensions routes are unused |
| Microversion gates | 8 checks on 2 values: 1.1 (masakariclient/osc/v1/notification.py:161), 1.2 (masakariclient/osc/v1/segment.py:75, masakariclient/osc/v1/segment.py:154, masakariclient/osc/v1/segment.py:228, masakariclient/osc/v1/segment.py:297) |
| Exception classes defined | 3 (masakariclient/common/exception.py:16, masakariclient/common/exception.py:25, masakariclient/common/exception.py:29), 10 distinct messages at 13 sites |
| Unit tests | 22 pass, 11 vectors, same call sequences in two runs; vectors cover only 3 of 15 command classes |
| Wire probe | 15 of 15 commands reached a request in both modes, after the stub's discovery fix |
| Stateful stub | 19 scenarios, 179 CLI invocations, 239 requests; each of the 15 commands succeeded at least once on its real route |
Points of attention
All reproduced on the stub; details in 02 § 4.
- **
segment deleteexits 0 when it fails** [observed]: every exception, including 403, 404, 409 and a missing catalog entry, is printed on stdout and swallowed (masakariclient/osc/v1/segment.py:271). A script cannot detect the failure. The other 14 commands exit 1. - **
--limitdoes not limit** [observed]: with 3 segments,segment list --limit 1shows all 3, in 4 requests. The SDK treats it as a page size (openstacksdk:openstack/resource.py:2434), while the help text promises a limit (masakariclient/osc/v1/segment.py:39). Same for the four list commands. - The default version 1.3 is fixed, with no negotiation [observed]: against a service whose maximum is 1.2, every command fails before sending a request. The CLI needs
--os-ha-api-versionto work with it. - **
--is_enabledis silently dropped below 1.2** [observed]:--os-ha-api-version 1.1 segment update x --is_enabled falsesends noPUTand exits 0 with the old value. - **
--os-ha-api-version 1or1.0lies about what is on the wire** [observed]: segments still go out at 1.2, notifications with no header, and the columns follow neither. - **
--markercannot be used as documented**: the help says "segment ID", the server wants the integerid(masakari:masakari/db/sqlalchemy/api.py:200), and onlysegment showdisplays it. A UUID gives 400 on the stub [observed for the stub's own check]. - **Unknown
--filterskeys are dropped without a word** [observed]:--filters bogus=1lists everything, exit 0, and a typo looks like an empty filter. - A create can succeed and report a failure [observed]: the follow-up
GETruns after thePOST. A failure there gives exit 1 although the resource exists, and a retry then gets a 409. A 500 on thatGETeven reads "No Notification found for". - **
--filtersgiven several times disables the;syntax** [observed]: the value goes to the server with the;inside it (masakariclient/common/utils.py:29). - Forward compatibility [observed with
-v]: the four host calls passsegment_id=, which raisesRemovedInSDK50Warning(masakariclient/osc/v1/host.py:294). With openstacksdk 5 they will fail withTypeError[inferred fromopenstacksdk:openstack/_utils.py:23].
Blind spots / [inferred]
- No real Masakari was contacted, as instructed. All wire facts are against stubs. The only link to the real service is reading its code and the exchanges recorded in
reverse-spec-masakari. - The stub's own errors are mine: messages such as
No failover segment with idare shaped after the service, not produced by it. The CLI behaviour around them is what is observed, not the texts. - **
OS_HA_API_VERSIONwas not exercised**, because the rule was to unsetOS_*. Read atmasakariclient/plugin.py:53. The same holds forha_api_versioninclouds.yaml. - Unit tests are weak evidence: the clients are mocks, and the tests of 6 commands call
take_actionwithout the parser, so they yield no vector, and 6 commands have no test at all (07 § 5). - **
APIVersionraisingUnsupportedVersion** (masakariclient/api_versions.py:58) was never reached: of the values tried, none produced a malformed default microversion. It may be dead code [inferred]. - Timeouts, TLS and retries belong to keystoneauth and were not exercised. Output formatters (
-f jsonand so on) belong to cliff;-f jsonwas run once onsegment show. - The reproduction of defect 2 assumes that the real service honours
limitand returnsidin each item, which its code does (masakari:masakari/api/openstack/ha/segments.py:46) [inferred for the whole chain].
Source: reverse-spec-python-masakariclient/00-summary_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.