# 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/
│   ├── 00-pre-deploy.md             # backups, capi-mgmt graceful teardown
│   ├── 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
│   ├── 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-016)
```

## v1 deployment order

1. Verify NetBox state — run NetBox imports if not already applied
   - `netbox/ipv4-prefixes-import.py` — required
   - `netbox/ipv6-mark-reserved.py` — required (Q3: tag existing IPv6 entries)
2. Run pre-flight checks (`scripts/pre-flight-checks.sh`)
3. Backup current cloud state (`runbooks/00-pre-deploy.md`)
4. Destroy existing OpenStack model (`runbooks/01-destroy-model.md`)
5. Deploy new bundle (`runbooks/02-deploy.md`)
6. Initialize Vault (`runbooks/03-vault-init.md`)
7. Set up Magnum domain (`runbooks/04-magnum-domain.md`)
8. Install Magnum CAPI Helm driver (`runbooks/05-magnum-capi-driver.md`)
9. Recreate tenant resources (`runbooks/06-tenant-setup.md`)
10. Populate DNS zones (`runbooks/07-dns-zones.md`)
11. Run validation (`runbooks/08-validate.md` + `scripts/validate.sh`)

## 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-008 DNS via Designate from day one** — static /etc/hosts for bootstrap;
  Designate handles tenant-level resolution (A records only for v1)
- **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
