# Charm IPv4 / IPv6 compatibility reference (VR1 bundle, Caracal 2024.1)

Created 2026-08-03 at operator request as a durable reference. Built from the repo's own
MEASURED research, not from general knowledge -- every IPv6 verdict cites its source. Where
the repo has NOT assessed a charm's IPv6 behaviour, the cell says **NOT ASSESSED** rather
than guessing (fabricating a compatibility claim is the cardinal sin, CLAUDE.md posture).

Scope: the 33 distinct charms in `bundle.yaml` (56 applications; `hacluster` x12 and
`mysql-router` x12 are subordinate instances of one charm each).

---

## Governing decision

**D-141 (ADOPTED 2026-08-03)** makes IPAM allocations dual-stack and status-distinguished:
v4 `active`, GUA v6 `reserved` until the consuming layer is capable. **This table IS the
named promotion gate for the API-charm v6 VIPs** -- a `reserved` v6 VIP block moves to
`active` only when both blocker layers below clear. See `docs/design-decisions.md` D-141.

---

## READ THIS FIRST -- v6 is blocked at TWO independent layers

A charm being "IPv6-capable" does not make the deployed cloud v6. Two separate things block
it, and they are at different layers:

1. **JUJU CONTAINER ADDRESSING (charm-independent).** Juju's MAAS/LXD provider assigns each
   container ONE address per NIC, family-blind, and lands v4 -- so API-charm containers get
   NO global v6 address at all. **LP #1723240, `Triaged`/Low, open since 2017, NOT fixed in
   juju 3.6 LTS or 4.0** (release notes checked 2026-08-03: no address-model change). This
   alone blocks EVERY v6 VIP today, regardless of charm. Measured here: keystone, ceph-mon
   and vault containers all hold zero global v6.
2. **PER-CHARM DEFECTS.** Even once a container HAS v6, the charms below marked "No"/"Partial"
   have their own v6 gaps that would still bite.

**IPv4 is the proven base for every charm** -- the entire cloud was built and verified on v4
across VR0 and VR1, so the IPv4 column is "Full" throughout by deployment evidence.

**Legend (IPv6 column):**
- **Capable** -- the charm code handles v6 correctly; the only thing stopping it is layer 1 (juju).
- **Partial** -- works in some paths / a fix has partly landed; caveats in Evidence.
- **No** -- the charm itself breaks on v6 at current pinned revision.
- **NOT ASSESSED** -- the repo has not measured this charm for v6; do not assume either way.
- **n/a** -- no VIP / not on a v6-relevant path.

---

## Table

| Charm | Inst. | IPv4 | IPv6 | Evidence (source) |
|---|---|---|---|---|
| barbican | 1 | Full | Capable | Frontend HAProxy binds v6 when `ipv6_enabled` (kernel sysctl, =0 on nodes); charms.openstack family. Blocked only by juju addressing. `stage5-prefer-ipv6-charm-research-20260731.txt` F1 |
| cinder | 1 | Full | Capable | charmhelpers HAProxy family, same as barbican. Same research |
| designate | 1 | Full | Capable | charms.openstack family. Same research |
| glance | 1 | Full | Capable | charmhelpers family. Same research |
| keystone | 1 | Full | Capable | charmhelpers family; MEASURED live 2026-08-03 -- v4 VIPs accepted, v6 VIPs rejected ONLY because container has no global v6 (`Invalid vips`), not a charm defect |
| magnum | 1 | Full | Capable | charms.openstack family. Same research |
| neutron-api | 1 | Full | Capable | charmhelpers family. Same research |
| nova-cloud-controller | 1 | Full | Capable | charmhelpers family. Same research |
| octavia | 1 | Full | Capable | charms.openstack family. Same research |
| openstack-dashboard | 1 | Full | Capable | charmhelpers family. Same research |
| placement | 1 | Full | Capable | charms.openstack family. Same research |
| hacluster | 12 | Full | **No** | Hard-writes `ip_version: ipv4` in `templates/corosync.conf`, 2.4/stable rev 166 (2026-06-29). **LP #2111852 `Fix Committed` but NOT RELEASED.** `CURRENT-STATE.md:2498-2500`. This is the VIP-manager itself -- it gates every API charm's HA VIP |
| mysql-innodb-cluster | 1 | Full | **No** | Builds bare `user:pw@addr` DB URIs invalid for a v6 literal without brackets. `CURRENT-STATE.md:2496-2498` |
| mysql-router | 12 | Full | **No** | Same bare-URI defect as mysql-innodb-cluster (x12 subordinate). Same source |
| ceph-osd | 1 | Full | **No** | Breaks on a v6-only plane BOTH ways: `prefer-ipv6:false` -> `inet_aton` then IPv4-only `IN A` lookup (**LP #2109798**, New); `true` -> bare `get_ipv6_addr()` returns only SLAAC, but VR1 nodes hold MAAS STATIC v6 (**LP #2061836**, New on ceph-osd). MEASURED here, rev 953. `CURRENT-STATE.md:2480-2489` |
| ceph-mon | 1 | Full | Partial | **LP #2061836 `Fix Committed` on charm-ceph-mon 2024-06-14** (the `get_ipv6_addr` half). The `inet_aton` half (LP #2109798) may still apply; ceph-mon not independently re-measured here -- verdict inferred from the LP, not from a live run |
| ovn-central | 1 | Full | **No** (data plane) | OVN documents the encap column as *"The IPv4 address of the encapsulation tunnel endpoint"* (`ovn-sb.xml:565`); every `ovn-encap-ip` in OVN 24.03's test suite is IPv4. `CURRENT-STATE.md:2501-2503`. Reported from capture, not independently re-verified |
| ovn-chassis | 2 | Full | **No** (data plane) | Same OVN encap IPv4-only constraint (ovn-chassis + ovn-chassis-octavia). Same source. NOTE: the `bridge-interface-mappings` / provider egress path is v4/v6-agnostic (MAC-based) and works |
| neutron-api-plugin-ovn | 1 | Full | NOT ASSESSED | Subordinate to neutron-api; its own v6 behaviour not separately measured. The OVN data-plane constraint above governs the encap, not this plugin's API path |
| ceph-radosgw | 1 | Full | NOT ASSESSED | Has a hacluster VIP (so inherits the hacluster "No" for its VIP), but the radosgw charm's own v6 handling was not measured |
| barbican-vault | 1 | Full | NOT ASSESSED | Subordinate; not measured for v6 |
| ceph-rbd-mirror | 1 | Full | NOT ASSESSED | Cross-DC replication charm; not measured for v6 |
| cinder-backup | 1 | Full | NOT ASSESSED | Subordinate; not measured for v6 |
| cinder-ceph | 1 | Full | NOT ASSESSED | Subordinate; not measured for v6 |
| designate-bind | 1 | Full | NOT ASSESSED | DNS backend; not measured for v6 |
| glance-simplestreams-sync | 1 | Full | NOT ASSESSED | Not measured for v6 |
| magnum-dashboard | 1 | Full | NOT ASSESSED | Horizon plugin; not measured for v6 |
| memcached | 1 | Full | NOT ASSESSED | Not measured for v6 |
| nova-compute | 1 | Full | NOT ASSESSED | Runs on the metal node (not a container), so the juju container-addressing blocker does not apply to it; its own v6 handling not measured |
| octavia-dashboard | 1 | Full | NOT ASSESSED | Horizon plugin; not measured for v6 |
| octavia-diskimage-retrofit | 1 | Full | n/a | Image-build helper; no VIP / not on a v6 network path |
| rabbitmq-server | 1 | Full | NOT ASSESSED | Messaging; not measured for v6 |
| vault | 1 | Full | NOT ASSESSED | Container measured to have no global v6 (layer-1 blocker applies); the vault charm's own v6 handling not separately assessed |

---

## Bottom line for the revert-to-IPv4 decision

- **Nothing about IPv4 was lost.** The current VIP overlay is DUAL-STACK -- every `vip:` line
  carries the v4 triple AND the v6 triple (e.g. `10.12.4.50 10.12.8.50 10.12.12.50 2602:...`).
  The v4 legs are live and already ACCEPTED by the charms; only the v6 legs are rejected.
  "Back to IPv4" = drop the v6 legs from `render/values/vr1-dc0-vips.yaml` and re-render; the
  working v4 config stays. Also recoverable from git at the parent of `a9e3258` (the D-139 GUA
  move) and reconstructable from `scripts/lib-net.sh`
  (`VIP_PREFIX_PROVIDER/ADMIN/INTERNAL = 10.12.4/8/12`).
- **The v6 work on the NODE PLANES is NOT wasted and should stay** -- node-to-node v6 is proven
  (D-139, gate G19), and the node planes are dual-stack. What reverts is the VIP FAMILY on the
  container-hosted API charms, not the node addressing.
- **Even a juju fix would not make this all-green today** -- hacluster, mysql, ceph-osd and OVN
  each carry their own v6 defect above, three of them tracked as open/unreleased Launchpad bugs.

## Maintenance

Update a row only from a MEASURED source and cite it. When a Launchpad bug changes state,
update the cell AND the citation. Promote a **NOT ASSESSED** to a verdict only after a real
measurement (charm artifact read or live run), never from a general expectation.
