# openstack-caracal-ipv4 — VR0 DC0 Omega Cloud (v1)

**Scope:** Charmed OpenStack Caracal (2024.1) IPv4-only testcloud deployment
on the 4-VM KVM lab, modeled in NetBox as **VR0 DC0 Omega Cloud**.

## v1 vs. v2 — read this first

This repository is the **v1 deliverable** — IPv4-only Caracal Charmed
OpenStack on the existing MAAS-provisioned network layout. v1 ships first
because the upstream router infrastructure is not yet IPv6-ready; deferring
on IPv6 lets v1 prove the bundle, Option B binding fix, Magnum CAPI graft,
Designate-from-day-one, and the hacluster relation pattern at testcloud scale
without waiting on network-side IPv6 readiness.

**v2** adds IPv6 / dual-stack per the address-family matrix retained as
v2-scope decisions in `docs/design-decisions.md` (D-004, D-004a). v2 will
ship either as a sibling overlay in this repository (`overlays/v2-dualstack.yaml`
on a `v2` branch) or as a separate repository — TBD when v2 work begins.

The IPv6 prefixes already imported into NetBox under VR0 DC0 remain in
NetBox as **Reservation status** to document the v2 intent without
implying they are active. See `netbox/ipv6-mark-reserved.py`.

## Repository purpose

This repository is the deployment method. Bundle, overlays, runbooks, and
validation scripts together describe everything required to bring up the
cloud from a clean MAAS-managed Juju model. Anyone with NetBox read access,
MAAS access, and the Juju controller can clone this repository and reproduce
the cloud.

## Source of truth

**NetBox is authoritative for IPAM.** Any IP, prefix, or VLAN value
referenced in this repository traces back to NetBox. The exception is
tenant per-project subnets, which under the v1 hybrid model (D-016) are
Neutron-managed within a NetBox-modeled upstream tenant pool — i.e., the
pool has NetBox standing, individual tenant subnets do not.

## Repository layout

```
openstack-caracal-ipv4/
├── README.md                        # this file
├── bundle.yaml                      # canonical Charmed OpenStack bundle (IPv4)
├── overlays/
│   └── vr0-dc0-testcloud.yaml       # 4-VM lab specifics; num_units=1 + hacluster
├── runbooks/
│   # (deprecated; see runbooks/deprecated/ - superseded by D-017 + D-018 + v1-do-doc-NN set)
│   ├── 01-destroy-model.md          # destroy openstack model + verify
│   ├── 02-deploy.md                 # juju deploy + settle wait
│   ├── 03-vault-init.md             # vault unseal + cert auth
│   ├── 04-magnum-domain.md          # domain-setup action + keystone wiring
│   ├── 04a-capi-bootstrap-cluster.md # capi-mgmt VM deploy + k3s + CAPI + ORC (D-017)
│   ├── 05-magnum-capi-driver.md     # pip install driver + kubeconfig + systemd
│   ├── 06-tenant-setup.md           # project, user, openrc, app credentials
│   ├── 07-dns-zones.md              # Designate zones + API VIP A records (v1)
│   └── 08-validate.md               # Roosevelt-rehearsal validation criteria
├── scripts/
│   ├── pre-flight-checks.sh         # pre-deploy sanity checks
│   └── validate.sh                  # end-to-end validation runner
├── netbox/
│   ├── README.md                    # what's here vs. what's deferred to v2
│   ├── ipv4-prefixes-import.py      # adds IPv4 prefixes + IPv4 tenant pool
│   └── ipv6-mark-reserved.py        # marks IPv6 entries as Reservation (Q3)
└── docs/
    ├── design-decisions.md          # architectural record (D-001 through D-019)
    └── netbox-vip-queue.md          # post-deploy NetBox imports (workstream 2)
```

## v1 deployment order

The deploy is executed via the `runbooks/v1-do-doc-NN-*.md` execution documents in numeric order:

| Doc | Purpose |
|---|---|
| `v1-do-doc-01-prep.md` | Pre-flight state check (repo, openrc, MAAS state of 5 VMs) |
| `v1-do-doc-02-pki.md` | Octavia PKI overlay generation |
| `v1-do-doc-03-destroy.md` | Conditional model + MAAS teardown (clean state for rebuild) |
| `v1-do-doc-04-deploy.md` | `juju deploy` + settle wait + on-disk PKI verification |
| `v1-do-doc-05-vault-init.md` | Vault initialization + cert cascade + admin-openrc regeneration |
| `v1-do-doc-06-magnum-domain.md` | Magnum Keystone domain setup |
| `v1-do-doc-07-capi-bootstrap.md` | CAPI bootstrap cluster + workload pivot |
| `v1-do-doc-08-magnum-driver.md` | Magnum CAPI Helm driver graft |
| `v1-do-doc-09-tenant.md` | Tenant project/user/openrc + Snapshot 2 |
| `v1-do-doc-10-validate.md` | D-011 acceptance criteria + Snapshot 3 |

NetBox imports are run separately (gated on external NetBox engineer review; see `netbox/README.md`).

## v1-specific design decisions (summary; see docs/design-decisions.md for full record)

- **D-015 v1/v2 fork** — IPv4-only v1; IPv6/dual-stack v2 deferred
- **D-016 IPv4 tenant pool hybrid model** — NetBox owns upstream `/16` pool;
  Neutron owns per-project subnets within it
- **D-003 Option B network architecture** — Provider `/22` carries both
  ext_net FIPs (`10.12.4.10–.223`) and OpenStack public API VIPs
  (`10.12.4.224–.254`) on the same L2 segment; fixes the tenant→API
  unreachability that caused Magnum OCCM crashloop on Bobcat testcloud
- **D-005 Ceph Squid** — matches Caracal default; rehearses Roosevelt
- **D-006 Vault HA backend = etcd + easyrsa**
- **D-007 Magnum from day one** — charm in bundle + CAPI Helm driver graft
- **D-019 (supersedes D-008) DNS scope reduction for v1** — Designate deferred
  to v2 alongside corporate DNS / NS-delegation work. Tenant subnets use public
  DNS (`1.1.1.1` / `1.0.0.1`) directly via `--dns-nameserver`.
  `*.cloud.neumatrix.local` FQDN tree remains internal-only, resolved via static
  `/etc/hosts` on bootstrap-relevant hosts.
- **D-009 Hacluster relations included at num_units=1** — decorative on
  testcloud; documents the relation pattern for Roosevelt scale-up
- **No OVN pinning on testcloud** — Roosevelt bare-metal will pin via `ovn-source`

## v2-scope decisions (deferred — read but do not action in v1)

- **D-004 Dual-stack/IPv6-only matrix** — applies in v2 only
- **D-004a Host management → Metal (Option A)** — applies in v2 only;
  v1 keeps openstack0-3 host management IPs on the storage fabric
- **VLAN modeling in NetBox** (Q2) — the VR0 DC0-VLANs group remains with
  only VID 240 (OS-Provider) imported during prior session work; remaining
  VLAN entries are deferred to v2 when actual VLAN tagging is in play.
  Currently MAAS uses untagged-per-fabric, so the additional VLAN entries
  would be misleading documentation
