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

Reverse-spec · Clients

python-masakariclient — Summary

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 as masakari: (commit ae41528e1ebc, read only, not run). The package installed in the venv is byte-identical to the clone (diff -r, excluding __pycache__).
  • References are file:line from 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

FileContent
01-cli-commands_stable-2026.2.mdshared mechanics, the 15 commands with arguments, requests and output columns, resource lifecycle as seen by the client
02-errors_stable-2026.2.mdexit codes, the 10 messages of the project, reproduced failures, and the defects
03-interactions_stable-2026.2.mdKeystone, discovery, microversions, requests sent to Masakari, sample frames
04-scenarios_stable-2026.2.md5 sequence diagrams with error branches
05-async-processing_stable-2026.2.mdnone, and what the user must poll
07-rewrite-pack_stable-2026.2.mdclient contract: what a service must do for these commands, evidence and limits
_verification_stable-2026.2.mdoutput 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

ProcessEntry pointRoleListens to / consumes
openstack (python-openstackclient)setup.cfg:29 (openstack.cli.extension, ha), setup.cfg:32 (openstack.ha.v1)loads the plugin and runs one commandargv; 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

SystemProtocolLibraryConfigurationUsage
KeystoneHTTP RESTkeystoneauth1--os-auth-url, clouds.yaml, OS_*token and catalog
MasakariHTTP RESTopenstacksdkcatalog type instance-ha or its alias ha; --os-ha-api-version (masakariclient/plugin.py:51)every command

Key figures

ItemCount
Commands15 (segments 5, hosts 5, notifications 3, VM moves 2), 55 own arguments
Service operations used15 of the 19 in the Masakari table, plus GET /v1 for discovery; GET / and the 2 /v1/extensions routes are unused
Microversion gates8 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 defined3 (masakariclient/common/exception.py:16, masakariclient/common/exception.py:25, masakariclient/common/exception.py:29), 10 distinct messages at 13 sites
Unit tests22 pass, 11 vectors, same call sequences in two runs; vectors cover only 3 of 15 command classes
Wire probe15 of 15 commands reached a request in both modes, after the stub's discovery fix
Stateful stub19 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.

  1. **segment delete exits 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.
  2. **--limit does not limit** [observed]: with 3 segments, segment list --limit 1 shows 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.
  3. 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-version to work with it.
  4. **--is_enabled is silently dropped below 1.2** [observed]: --os-ha-api-version 1.1 segment update x --is_enabled false sends no PUT and exits 0 with the old value.
  5. **--os-ha-api-version 1 or 1.0 lies about what is on the wire** [observed]: segments still go out at 1.2, notifications with no header, and the columns follow neither.
  6. **--marker cannot be used as documented**: the help says "segment ID", the server wants the integer id (masakari:masakari/db/sqlalchemy/api.py:200), and only segment show displays it. A UUID gives 400 on the stub [observed for the stub's own check].
  7. **Unknown --filters keys are dropped without a word** [observed]: --filters bogus=1 lists everything, exit 0, and a typo looks like an empty filter.
  8. A create can succeed and report a failure [observed]: the follow-up GET runs after the POST. A failure there gives exit 1 although the resource exists, and a retry then gets a 409. A 500 on that GET even reads "No Notification found for".
  9. **--filters given several times disables the ; syntax** [observed]: the value goes to the server with the ; inside it (masakariclient/common/utils.py:29).
  10. Forward compatibility [observed with -v]: the four host calls pass segment_id=, which raises RemovedInSDK50Warning (masakariclient/osc/v1/host.py:294). With openstacksdk 5 they will fail with TypeError [inferred from openstacksdk: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 id are shaped after the service, not produced by it. The CLI behaviour around them is what is observed, not the texts.
  • **OS_HA_API_VERSION was not exercised**, because the rule was to unset OS_*. Read at masakariclient/plugin.py:53. The same holds for ha_api_version in clouds.yaml.
  • Unit tests are weak evidence: the clients are mocks, and the tests of 6 commands call take_action without the parser, so they yield no vector, and 6 commands have no test at all (07 § 5).
  • **APIVersion raising UnsupportedVersion** (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 json and so on) belong to cliff; -f json was run once on segment show.
  • The reproduction of defect 2 assumes that the real service honours limit and returns id in 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.