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

Reverse-spec · Services

cloudkitty — Change history

Change history — CloudKitty — branch stable/2026.2

Branch stable/2026.2 @ 0685cc330e83 — repository https://opendev.org/openstack/cloudkitty — analysed on 2026-11-09

  • Range: 24.0.0..stable/2026.2 (bf6195a4cd4b..0685cc330e83), i.e. the whole 2026.2 development cycle since the 2026.1 release, 32 non-merge commits. The automatic range (since stable/2026.2 left master, 95b73e36cb2c..0685cc330e83) holds only the two release-bot commits #31 and #32, so it was widened on purpose.
  • Target: none given. No commit is marked present/absent; the carry-over plan lists every non-maintenance commit in application order.
  • Raw facts: [_inventory/history_stable-2026.2.md](_inventory/history_stable-2026.2.md) and .json (trailers, files, release notes, overlaps).
  • Categories (corrected after reading the diffs): 2 security-relevant hardening, 4 fixes, 4 features, 2 upgrade, 1 configuration-sample, 1 refactor, 18 maintenance. The script's categories were adjusted where noted ("category corrected").

Summary

#CommitDateCategoryChangeBug / storyImpact on this spec
368796c97046d2026-03-04config sampleauth_section and the other keystoneauth options are listed in the sample for collector_gnocchi, fetcher_gnocchi, fetcher_keystone, storage_gnocchi—03 § 3.2, § 4 (documentation only)
522807c7eca9c2026-03-18fix (performance; category corrected)rating rules are no longer loaded for deactivated scopes—05 § 1, 03 § 2.3
720bbf9d55c152026-03-31hardeningnew [storage_influxdb]/timeout (60 s) on Flux HTTP queries—03 § 5.1
101a54c8ac40352026-02-18featurenew Aetos collector (Prometheus behind Keystone auth); Prometheus code split into base + concrete classesspec 96675300, 03 § 3.3
11a45fbeeab0492026-01-27featureLoki structured metadata: always written; used in queries when [storage_loki]/use_structured_metadata = true—03 § 5.3
1263ecb1e71a382026-04-09upgradethe cloudkitty-api WSGI script and cloudkitty/api/app.wsgi are removed; use cloudkitty.wsgi.api:application—00 Processes
1513c0dcfe707a2026-04-09packaging (category corrected)setup.cfg metadata, scripts and entry points moved to pyproject.toml—00 (entry points now cited in pyproject.toml)
16f213c4dd4a682026-05-02upgradePython ≥ 3.11 (3.10 dropped), 3.14 added—runtime
2043ecd5406fba2026-05-12config sample (category corrected)sample image.size metric gets force_granularity: 300—03 § 3.2
244cb28f1983752026-05-26fixPOST /v2/scope with active=false no longer answers 500—01 § 6.4, 02 § 2.5
255bb59c0048c22026-06-18fix (data loss)a failed Loki push now raises PushError, so the period is retried instead of being marked processed—02 § 3, 03 § 5.3
26349cda233a7f2026-06-19fix (behaviour change; category corrected)Loki entries are timestamped with the period start instead of the period end—03 § 5.3
281ed51c37e5b32026-08-24fixrevert of a 2024 ES/OpenSearch fix that conflicted with a later one; /v2/summary with a type filter works again on ES/OSstory 201186803 § 5.2
2947205370cb852026-08-29refactortypo fix: filter_unecessary_measurements → filter_unnecessary_measurements, log text occured → occurred—02 § 3 (log text)

Change specifications

3. List the keystoneauth options of four sections — config sample

  • What changed: list_opts now adds ks_loading.get_session_conf_options() and get_auth_common_conf_options() to collector_gnocchi, fetcher_gnocchi, fetcher_keystone and storage_gnocchi (cloudkitty/common/config.py:47-68, cloudkitty/common/config.py:82-86). These options were already registered and honoured at run time (cloudkitty/collector/gnocchi.py:78-79, cloudkitty/fetcher/keystone.py:46-47); only oslo-config-generator output changes, notably auth_section now appears in the sample.
  • Why: the generated cloudkitty.conf.sample and the configuration reference were missing them.
  • Upgrade impact: none at run time.
  • Carrying it over: standalone, no prerequisite. Only worth it if the target ships a generated sample.

5. Do not load rating rules for deactivated scopes — fix (performance)

  • Before: Worker.__init__ and every iteration of Worker.run called refresh_rating_rules(), i.e. the full hashmap and pyscripts rule load (03 § 2.3), **even for scopes that are then skipped because active is false**.
  • After: the call moves to the start of do_execute_scope_processing (cloudkitty/orchestrator.py:418-419), which runs only once the active check has passed (cloudkitty/orchestrator.py:406-415). Rules are still reloaded for every period processed, because rules carry validity windows and each period must be rated with the rules valid at its start (commit message).
  • Impact on this spec: 05 § 1 step 5 describes the new order. The SQL load per scope cycle (03 § 2.3) now applies only to active scopes with a ready period.
  • Upgrade impact: none; lower database load on deployments with many deactivated scopes.
  • Carrying it over: 3 lines in cloudkitty/orchestrator.py; no test in the commit. Conflicts are unlikely unless the target refactored Worker.

7. Timeout on InfluxDB v2 HTTP queries — hardening

  • What changed: new [storage_influxdb]/timeout (float, 60 s, min 0) (cloudkitty/storage/v2/influx.py:89-93), passed to the requests.post that sends Flux queries (cloudkitty/storage/v2/influx.py:707-717).
  • Why: a stuck InfluxDB froze API requests and processor workers; bandit B113 (request without timeout).
  • Scope, read from the code: only the Flux query path of the InfluxDB 2 client uses it. The InfluxDB 1 client (influxdb.InfluxDBClient, cloudkitty/storage/v2/influx.py:133-141) and the v2 write/delete APIs (InfluxDBClient(timeout=query_timeout), cloudkitty/storage/v2/influx.py:516-520) are unchanged [inferred: they keep their library defaults].
  • Upgrade impact: a Flux query longer than 60 s now fails (500 on the API, retry on the processor) where it used to wait.
  • Carrying it over: standalone; release note releasenotes/notes/influxdb-timeout-57aba639d07b8c8b.yaml.

10. Aetos collector — feature

  • What changed:
    • The Prometheus collector and client are split into PrometheusCollectorBase / PrometheusClientBase and concrete classes (cloudkitty/collector/prometheus_base.py:63-229, cloudkitty/common/prometheus_client_base.py:18-54), without behaviour change to the PromQL built (cloudkitty/collector/prometheus_base.py:116-174).
    • New aetos collector: same queries, sent through python-observabilityclient over a keystoneauth session to the metric-storage endpoint of the catalogue (cloudkitty/collector/aetos.py:27-83, cloudkitty/common/aetos_client.py:28-75); new section [collector_aetos] with interface (public) and region_name, plus keystoneauth options.
    • Entry point aetos (pyproject.toml:55); new requirement python-observabilityclient>=1.1.0 (requirements.txt:39).
  • Why: rate from Prometheus without exposing it unauthenticated (spec https://review.opendev.org/c/openstack/cloudkitty-specs/+/966753).
  • Impact on this spec: 03 § 3.3. Aetos errors from python-observabilityclient (PrometheusAPIClientError) are wrapped into PrometheusResponseError, then CollectError (cloudkitty/common/aetos_client.py:56-75, cloudkitty/collector/prometheus_base.py:196-202).
  • Upgrade impact: none unless [collect]/collector = aetos; the Prometheus fetcher's import path changed (cloudkitty/fetcher/prometheus.py:18-19), which matters only to out-of-tree code importing the old names.
  • Carrying it over: large (≈ 900 lines with tests); prerequisite for any later Prometheus fix that touches cloudkitty/collector/prometheus_base.py. Requires an Aetos release supporting the time and timeout query parameters (commit message).

11. Loki structured metadata — feature

  • What changed:
    • Every pushed entry now carries structured metadata for type, user, unit, flavor_name when present (cloudkitty/storage/v2/loki/client.py:30, cloudkitty/storage/v2/loki/client.py:346-365).
    • New [storage_loki]/use_structured_metadata (false) (cloudkitty/storage/v2/loki/__init__.py:92-99). When true, queries filter on those fields before | json, other filters become groupby_<key>="…" after | json, and totals read indexed fields directly from the stream (cloudkitty/storage/v2/loki/client.py:108-182, cloudkitty/storage/v2/loki/client.py:414-425).
    • Query building is factored into _build_query, shared by retrieve and delete (cloudkitty/storage/v2/loki/client.py:271-302).
  • Why: query performance on Loki 3.0+.
  • Upgrade impact: requires Loki ≥ 3.0 for the write side **[inferred: older Loki rejects the third element of a values entry]**; enable the query option only once data written without metadata has expired (commit message). Multi-valued filters keep only their first value (cloudkitty/storage/v2/loki/client.py:140-141).
  • Carrying it over: prerequisite of #25 and #26 (same file). Apply in order 11 → 25 → 26.

12. Remove the pbr WSGI script — upgrade

  • What changed: cloudkitty/api/app.wsgi, the wsgi_scripts entry cloudkitty-api and the mod_wsgi install page are removed. The supported entry point is the module cloudkitty.wsgi.api:application (cloudkitty/wsgi/api.py:19-24), added in 2025.
  • Upgrade impact (release note releasenotes/notes/rm-wsgi-scripts-b944f2957bb7f480.yaml): deployment tools must point uWSGI/gunicorn at cloudkitty.wsgi.api:application, or ship their own .wsgi file for mod_wsgi.
  • Carrying it over: packaging change; depends on the target's build system (#15).

15. Move packaging to pyproject.toml — packaging

  • What changed: project metadata, console scripts (pyproject.toml:34-38) and every stevedore namespace (pyproject.toml:40-79) move from setup.cfg to pyproject.toml; no entry point is added or removed by this commit.
  • Upgrade impact: none for operators; packagers need a recent setuptools/pbr.
  • Carrying it over: rewrite rather than cherry-pick if the target's setup.cfg differs.

16. Python ≥ 3.11 — upgrade

requires-python = ">=3.11" (pyproject.toml:15); 3.14 added to the classifiers. Upgrade note: 3.10 hosts must be upgraded first. Not to be carried to an older branch.

20. Sample image.size granularity — config sample

force_granularity: 300 is added to the sample image.size metric (etc/cloudkitty/metrics.yml:29-32), matching Gnocchi's default archive policy; without it the Gnocchi collector asks for granularity 3600 (cloudkitty/collector/gnocchi.py:115), which a 300 s archive policy cannot serve. Existing deployments must update their own metric file; nothing changes automatically.

24. POST /v2/scope with active=false — fix

  • Before: the handler created the scope, then re-read it with get_all(identifier=…), whose default active=1 hides inactive scopes → IndexError → 500, although the row was created.
  • After: the re-read passes active=None (cloudkitty/api/v2/scope/state.py:270-272); the API returns 200 with the created scope.
  • Remaining gap (read from the code): the duplicate check before creation still uses the default active=1 (cloudkitty/api/v2/scope/state.py:249), so creating a scope whose id exists but is inactive is not refused by the API and ends on the table's unique key or in a second row for another fetcher/collector [inferred].
  • Carrying it over: one line; standalone.

25. Raise on Loki push failure — fix (data loss)

  • Before: a non-204 answer from POST /push was only logged; the orchestrator then advanced last_processed_timestamp, so the period's rated data was lost silently.
  • After: PushError(status_code, text) is raised (cloudkitty/storage/v2/loki/client.py:234-241, cloudkitty/storage/v2/loki/exceptions.py:36-42); internal_run logs it and retries the scope at the next loop (cloudkitty/orchestrator.py:716-725).
  • Side effect: pushes also happen from add_point when a buffer fills (cloudkitty/storage/v2/loki/client.py:367-370); a failure there now aborts the frame part-way, and the retry re-pushes the points already accepted [inferred: duplicates in Loki].
  • Carrying it over: after #11.

26. Loki entry timestamp = period start — fix (behaviour change)

  • Before: each entry was timestamped with the period end; queries over [begin, end) returned the data of the previous period and Loki rejected entries whose end was in the future.
  • After: the period start (cloudkitty/storage/v2/loki/client.py:324-327); end stays in the JSON line.
  • Upgrade impact: data written before and after the upgrade are offset by one period: a query, a reprocessing purge or a scope reset spanning the upgrade time sees the boundary period twice or misses it [inferred]. Consider reprocessing the periods around the upgrade.
  • Carrying it over: after #11; one line.

28. Revert the 2024 ES/OpenSearch total fix — fix

  • What changed: ElasticsearchClient.total and OpenSearchClient.total no longer wrap metric_types into a list themselves; _build_must already does it since 677fc286f7fe (2025-10-01, part of 24.0.0) (cloudkitty/storage/v2/elasticsearch/client.py:70-86).
  • Why: with both changes, a list given by /v2/summary became [[type]] and every summary filtered by type failed (story 2011868). The removed release note was the one of the reverted fix (story 2011128).
  • Carrying it over: only if the target has both 2613a4251485 and 677fc286f7fe; otherwise skip it.

29. Typo fixes — refactor

Renames the static method GnocchiCollector.filter_unecessary_measurements to filter_unnecessary_measurements (cloudkitty/collector/gnocchi.py:459-460, cloudkitty/collector/gnocchi.py:496-497) and fixes a WARNING text. Breaks only out-of-tree code calling the old name. Log-based alerts on occured must be updated.

Maintenance-only changes

#CommitSubjectWhy it is usually not carried over
175ce6403504fdevstack: Modernize authinfos optionsdevstack plugin
2a6c77db6a16cdevstack: Use common function to manage keystoneauth optionsdevstack plugin
4405a9cbfd311Update master for stable/2026.1release bot (reno index)
68f97464a363dRemove unnecessary direct dependency on Pygmentsrequirements hygiene
8302180bfd391Drop unnecessary direct dependency on kombutest requirements
98de59c149cf1Fix missing oslo.policy optionsunit-test fixture only
1310ee031e6768Update loki to newer upstream release for testingCI
14c7b9b74a40cezuul: Use ansible variable to configure tempest pluginsCI
17f6bf20dc094eUse pip to install from sourcesdevstack
18aac92543e040Doc: define fetchers endpoints in to pyproject.tomldocumentation
1903bc6be72967Doc: use the code-block directive for codedocumentation
215206e90693d1doc: Update Ubuntu package informationdocumentation
222245e71c30f3doc: Use dnf in CentOS/RHELdocumentation
2389a8140ef453Skip tempest job for irrelevant filesCI
2740323f7428afdoc: Warn that aggregation_method must match the archive policy (bug 2160102)documentation; operationally relevant: a Gnocchi aggregation_method absent from the archive policy returns no data
30678e139ddf41Fix CI testsCI
31d775ce1d2ce4Update .gitreview for stable/2026.2release bot
320685cc330e83Update TOX_CONSTRAINTS_FILE for stable/2026.2release bot

Carry-over plan

No target was given, so presence was not checked. In application order (oldest author date first, Loki chain kept together), for a target branched before 24.0.0's successor:

git cherry-pick -x a45fbeeab049   # 11 Loki structured metadata (prerequisite of 25, 26)
git cherry-pick -x 1a54c8ac4035   # 10 Aetos collector (needs python-observabilityclient>=1.1.0)
git cherry-pick -x 68796c97046d   #  3 keystoneauth options in the config sample
git cherry-pick -x 22807c7eca9c   #  5 no rule loading for deactivated scopes
git cherry-pick -x 20bbf9d55c15   #  7 InfluxDB timeout
git cherry-pick -x 43ecd5406fba   # 20 sample image.size granularity
git cherry-pick -x 4cb28f198375   # 24 POST /v2/scope active=false
git cherry-pick -x 5bb59c0048c2   # 25 Loki push failure raises
git cherry-pick -x 349cda233a7f   # 26 Loki timestamp = period start (behaviour change)
git cherry-pick -x 1ed51c37e5b3   # 28 ES/OS revert (only if 2613a4251485 and 677fc286f7fe are both present)
git cherry-pick -x 47205370cb85   # 29 typo fixes

Left out on purpose: #12, #15, #16 (packaging and runtime policy of the 2026.2 release, to be decided per target).

For OpenKeel, none of these needs carrying over (OpenKeel does not ship CloudKitty); they matter as behaviour to match or avoid if openkeel-pricing aims at CloudKitty API compatibility: #24 and #26 change observable API/storage results, #25 shows the expected retry semantics when the storage refuses a write.

Source: reverse-spec-cloudkitty/06-change-history_stable-2026.2.md. The _rewrite/ and _inventory/ files are not published on the site.