Newer
Older
openstack-caracal-dc-dc / docs / changelog-20260731-prefer-ipv6-research.md

Changelog 2026-07-31 -- the prefer-ipv6 / v6 VIP charm research

Session changelog (GA-R2/D1: ONE per session). Branch dc-dc-stage5-preconditions. Status claims live ONLY in docs/CURRENT-STATE.md.

Context: bundle deploy attempt 1 failed 2026-07-31 with unknown option "prefer-ipv6" on barbican, and the operator ruled "Research what those 6 charms do with v6 VIPs first (Recommended)". Stage 5 is blocked on that research. This session executes it. Read-only throughout: no cloud mutation, no overlay edit, no ruling adopted.


Item 1 -- docs/audit/stage5-prefer-ipv6-charm-research-20260731.txt (NEW)

What. The capture answering the ruled question, plus two findings that came out of the same measurement.

Method, and why it is not the Charmhub config-yaml API. The attempt-1 root cause was measured against config-yaml, which answers only is the knob declared. It cannot answer what the charm does. This research downloads the charm each app actually deploys -- juju download <charm> --channel <pinned> --base ubuntu@22.04 --arch amd64 from voffice1 -- and reads the templates and code inside it. Revisions are recorded in the capture because 2024.1/stable moves. Two declaring charms (keystone 857, cinder 820) were downloaded as CONTROLS: without one, "binds v4 only" and "binds v6 by another mechanism" cannot be told apart.

The answer. prefer-ipv6 is not what makes HAProxy bind :::port, and never was, for any of the thirteen. In both template families the v6 frontend bind is gated on ipv6_enabled = not is_ipv6_disabled() -- a read of the kernel net.ipv6.conf.all.disable_ipv6 sysctl. Measured 0 on a live MAAS-deployed jammy node in this DC. The v6 VIP is assigned by pacemaker on per-address family detection, also independent of the option. Vault ships no haproxy template at all and its listener is the hardcoded literal [::]:8200.

What the option really does: it is a unit address-family switch -- get_relation_ip() returns early with the unit's IPv6 address for EVERY relation, ignoring the network-space binding; plus bind_host ::, ip6-localhost stats, and keystone's sync_db_with_multi_ipv6_addresses. The value that sounds like a bind address, haproxy_host, is consumed by NO template in any charm downloaded.

Consequence recorded, not acted on: provider-bundle-check invariant 9's mechanism claim is factually wrong; when a ruling lands the invariant must be REPLACED with a charm-schema-aware one and proven able to fail in both directions, never deleted to go green.

Revert. git rm docs/audit/stage5-prefer-ipv6-charm-research-20260731.txt. The file is a read-only capture; nothing depends on it but the CURRENT-STATE entry in item 2.

Item 2 -- docs/CURRENT-STATE.md section 1: the research result

What. The research outcome appended under the 2026-07-31 ruling block that records the question -- the answer, its evidence, the invariant-9 consequence, the new question about the seven declaring charms, the option-name sweep result, and the runbook defect. Required in the same commit by GA-R1 rule 8 (C1); repo-lint L10 enforces it.

Revert. git revert this commit, or delete the appended block; the preceding ruling text is unchanged and still reads correctly on its own.

Item 3 -- MEASUREMENT ONLY (no artifact): full option-name sweep of the dc0 deploy input

What. Attempt 1 proved juju deploy --dry-run does not validate config option NAMES, and juju aborts the whole bundle atomically on the first bad one -- so a second unknown option elsewhere costs another full attempt. Every option assignment in attempt 1's exact input (bundle.yaml + vr1-dc0-vips + vr1-dc0-machines + vr1-dc0-octavia-pki) was compared against each charm's own config.yaml downloaded at its pinned channel.

Result: 56 applications, 81 option assignments, 20 charm schemas, 0 unresolvable, and the only findings are prefer-ipv6 on the same six. No further option-name failure is waiting for attempt 2. An unreadable or unrecognised schema REFUSES rather than passing.

Not built as a gate, deliberately. Hard rule 1 plus the standing operator directive: hardening is out of scope unless it blocks the deploy, and this one-shot measurement already de-risks attempt 2. The method is reproduced verbatim in the capture so it can be re-run or promoted later. CURRENT-STATE already records that no gate in this repo reads a charm config schema.

Scope, stated so it is not over-read. It checked option NAMES, for the dc0 input only. Two extensions are OWED before the redeploy and are sequenced after the ruling: option VALUE TYPES (every downloaded config.yaml carries the type: field this pass discarded), and the dc1 input, which is unswept.

Revert. Nothing to revert -- no repo artifact was created by this item.

Item 5 -- MEASUREMENT ONLY: what option (b) would actually cost

What. Before putting the fork to the operator, the implementation cost of (b) was measured rather than assumed. prefer-ipv6: true is INJECTED UNCONDITIONALLY by scripts/render-dc-overlays.py:243-246 for every app whenever fam == "dual", and family: dual is a SINGLE TOP-LEVEL key at render/values/vr1-dc{0,1}-vips.yaml:3 -- not per-app data.

Consequence. There is no value to edit. (b) means teaching the renderer which charms declare the option, re-pointing tests/render-drift, and replacing provider-bundle-check invariant 9 -- a code change with a harness, not a one-line data fix. The injection's own inline comment repeats the mechanism claim this session's research refutes.

Revert. Nothing to revert.

Item 4 -- LOGGED NOT FIXED: the dc0 deploy block omits a non-no-op overlay

What. runbooks/dc-dc-phase4-juju-bundle-per-dc.md:553-557 gives the dc0 deploy without overlays/vr1-dc0-machines.yaml, while the dc1 block three lines below includes its machines overlay. Measured, the overlay's ONLY delta to the merged input is ovn-chassis.options.bridge-interface-mappings = 'br-ex:52:54:00:8c:2a:8c br-ex:52:54:00:50:48:88' -- the two dc0 compute provider MACs. Deploying dc0 exactly as the runbook reads would leave ovn-chassis with no provider bridge mapping, which surfaces later as tenant networks with no external path, not as a deploy error. Attempt 1 as executed correctly included the overlay.

Why not fixed here. Hard rule 1 -- this session's step is the research. It is DOCFIX material and is recorded in CURRENT-STATE and in the capture so it cannot be lost.

Revert. Nothing to revert.


What was NOT done, stated so it is not assumed

  • The overlay is untouched and R2 is unamended. The operator's ruling was to research, not to fix; the fork between (b) and (c) is theirs.
  • No prefer-ipv6 was removed from anything, including the seven charms that declare it -- that is a separate, newly-raised question.
  • provider-bundle-check is unchanged. Its invariant 9 is now known to rest on a wrong mechanism claim, but changing a gate before the ruling it gates would be the wrong order.
  • No cloud state changed. The vr1-dc0 model is still empty.