# ============================================================
# Caracal 2024.1 — VR0 DC0 Omega Cloud testcloud rebuild bundle
# ============================================================
# Generated: 2026-05-22
# Replaces: bundle-pre-destroy.yaml (Bobcat 2023.2)
# Charm channels: verified against Charmhub 2026-05-22 (see Caracal_Rebuild handoff D-002)
# Bindings: public:provider, else:metal for API charms; all-metal for backend charms
# HA chain: ALL hacluster subordinates + vip configs + :ha relations COMMENTED OUT
# until NetBox VIP allocations land in 10.12.4.224-.254
# Vault HA: etcd backend + easyrsa CA bootstrap live; vault-hacluster commented
# Magnum: Layer A only — CAPI driver graft is Layer B (runbooks/04a + 05)
# Octavia: lb-mgmt PKI options present but VALUES commented out — source from
# either Bobcat backup (~/backups/pre-caracal-destroy-2026-05-22/)
# or fresh octavia-cert-runbook (TBD)
# OVN tunnels: remain on metal space (Bobcat-proven); enp8s0 3_data v2 improvement
# Resources: omitted — let charms use latest available resource revisions
# ============================================================
name: vr0-dc0-omega-caracal-testcloud
description: |
Charmed OpenStack Caracal (2024.1) on Ubuntu 22.04 LTS (Jammy) deployed via Juju 3.6 bundle
against MAAS-managed VMs (openstack0-3, virsh).
Decisions referenced (see Caracal_Rebuild handoff):
D-001 Path 2A (Juju-bundle paradigm)
D-002 channel matrix
D-003 Option B (provider /22 carries FIPs + API VIPs)
D-005 Ceph Squid
D-006 Vault HA via etcd + easyrsa
D-007 Magnum Layer A + Layer B graft
D-008 Designate day-one
D-009 hacluster subordinates (decorative on testcloud)
D-016 IPv4-only v1
D-018 MAAS-release-direct teardown
default-base: ubuntu@22.04/stable
variables:
# ----- UCA pocket + Ceph source ----------------------------------------------
openstack-origin: &openstack-origin cloud:jammy-caracal
ceph-source: &ceph-source cloud:jammy-caracal
# ----- Bindings for external-API-facing charms (public on provider) ----------
api-bindings: &api-bindings
"": metal
public: provider
admin: metal
internal: metal
shared-db: metal
amqp: metal
certificates: metal
cluster: metal
ha: metal
# ----- Bindings for backend / internal-only charms (all metal) ---------------
# Used for ceph-mon (Ceph public network IS metal, not OpenStack public),
# ceph-osd, ovn-central, mysql-innodb-cluster, rabbitmq-server, nova-compute, etc.
internal-bindings: &internal-bindings
"": metal
machines:
"8":
constraints: arch=amd64 tags=openstack
"9":
constraints: arch=amd64 tags=openstack
"10":
constraints: arch=amd64 tags=openstack
"11":
constraints: arch=amd64 tags=openstack
applications:
# =====================================================================
# Datastores: MySQL InnoDB Cluster, RabbitMQ, Vault + HA backend
# =====================================================================
mysql-innodb-cluster:
charm: mysql-innodb-cluster
channel: 8.0/stable
num_units: 3
to: [lxd:8, lxd:9, lxd:10]
bindings: *internal-bindings
constraints: arch=amd64
rabbitmq-server:
charm: rabbitmq-server
channel: 3.9/stable
num_units: 1
to: [lxd:10]
bindings: *internal-bindings
constraints: arch=amd64
vault:
charm: vault
channel: 1.8/stable
num_units: 1 # 3 on Roosevelt (D-009)
to: [lxd:11]
options: {}
# TODO(netbox): uncomment vip + vault-hacluster app + :ha relation
# atomically once provider VIP is allocated from 10.12.4.224-.254
# vip: 10.12.4.<XXX>
bindings: *api-bindings
constraints: arch=amd64
vault-mysql-router:
charm: mysql-router
channel: 8.0/stable
etcd:
charm: etcd
channel: latest/stable # support charm; not in OS delivery table
num_units: 3 # Vault HA backend (D-006)
to: [lxd:8, lxd:9, lxd:10]
bindings: *internal-bindings
constraints: arch=amd64
# Note: etcd charm has its OWN `channel:` config option (controls etcd snap).
# Leaving at charm default; revisit if a specific etcd binary version is needed.
easyrsa:
charm: easyrsa
channel: latest/stable
num_units: 1 # One-shot CA for etcd bootstrap (D-006)
to: [lxd:8]
bindings: *internal-bindings
constraints: arch=amd64
# =====================================================================
# Identity: Keystone
# =====================================================================
keystone:
charm: keystone
channel: 2024.1/stable
num_units: 1 # 3 on Roosevelt (D-009)
to: [lxd:8]
options: {}
# TODO(netbox): vip + keystone-hacluster + :ha relation atomic uncomment
# vip: 10.12.4.<XXX>
bindings: *api-bindings
constraints: arch=amd64
keystone-mysql-router:
charm: mysql-router
channel: 8.0/stable
# =====================================================================
# Image: Glance + simplestreams-sync
# =====================================================================
glance:
charm: glance
channel: 2024.1/stable
num_units: 1
to: [lxd:11]
options: {}
# TODO(netbox): vip + glance-hacluster + :ha relation
bindings: *api-bindings
constraints: arch=amd64
glance-mysql-router:
charm: mysql-router
channel: 8.0/stable
glance-simplestreams-sync:
charm: glance-simplestreams-sync
channel: 2024.1/stable
num_units: 1
to: [lxd:8]
bindings: *internal-bindings
constraints: arch=amd64
# =====================================================================
# Compute: Nova cloud-controller + compute + Placement
# =====================================================================
nova-cloud-controller:
charm: nova-cloud-controller
channel: 2024.1/stable
num_units: 1
to: [lxd:11]
options:
console-access-protocol: novnc
network-manager: Neutron
# TODO(netbox): vip + nova-cloud-controller-hacluster + :ha relation
bindings: *api-bindings
constraints: arch=amd64
nova-compute:
charm: nova-compute
channel: 2024.1/stable
num_units: 3
to: ["9", "10", "11"]
options:
config-flags: default_ephemeral_format=ext4
enable-live-migration: true
enable-resize: true
migration-auth-type: ssh
resume-guests-state-on-host-boot: true
virt-type: qemu # Testcloud nested-KVM; Roosevelt will use 'kvm'
bindings: *internal-bindings
constraints: arch=amd64
storage:
ephemeral-device: loop,10240M
ncc-mysql-router:
charm: mysql-router
channel: 8.0/stable
placement:
charm: placement
channel: 2024.1/stable
num_units: 1
to: [lxd:11]
options: {}
# TODO(netbox): vip + placement-hacluster + :ha relation
bindings: *api-bindings
constraints: arch=amd64
placement-mysql-router:
charm: mysql-router
channel: 8.0/stable
# =====================================================================
# Networking: Neutron + OVN
# =====================================================================
neutron-api:
charm: neutron-api
channel: 2024.1/stable
num_units: 1
to: [lxd:9]
options:
enable-ml2-port-security: true
flat-network-providers: physnet1
neutron-security-groups: true
# TODO(netbox): vip + neutron-api-hacluster + :ha relation
bindings: *api-bindings
constraints: arch=amd64
neutron-api-mysql-router:
charm: mysql-router
channel: 8.0/stable
neutron-api-plugin-ovn:
charm: neutron-api-plugin-ovn
channel: 2024.1/stable
ovn-central:
charm: ovn-central
channel: 24.03/stable
num_units: 3
to: [lxd:8, lxd:9, lxd:10]
bindings: *internal-bindings
constraints: arch=amd64
# ovn-chassis: subordinate to nova-compute. MAC-based bridge-interface-mappings
# captured from MAAS 2026-05-22 (Bobcat used hardcoded 'enp1s0' — anti-pattern fix).
# The charm picks whichever MAC is found locally per unit; non-matching MACs ignored.
ovn-chassis:
charm: ovn-chassis
channel: 24.03/stable
options:
ovn-bridge-mappings: physnet1:br-ex
bridge-interface-mappings: >-
br-ex:52:54:00:3d:fd:54
br-ex:52:54:00:9d:63:77
br-ex:52:54:00:89:7f:ce
br-ex:52:54:00:99:fc:c2
# ovn-chassis-octavia: separate ovn-chassis app, subordinate to octavia.
# No bridge-interface-mappings — matches Bobcat-proven pattern (Octavia mgmt
# traffic rides Neutron tenant overlay; no external physnet bridge needed here).
ovn-chassis-octavia:
charm: ovn-chassis
channel: 24.03/stable
# =====================================================================
# Block Storage: Cinder + cinder-ceph
# =====================================================================
cinder:
charm: cinder
channel: 2024.1/stable
num_units: 1
to: [lxd:9]
options:
block-device: None
glance-api-version: 2
# TODO(netbox): vip + cinder-hacluster + :ha relation
bindings: *api-bindings
constraints: arch=amd64
storage:
block-devices: loop,10240M
cinder-mysql-router:
charm: mysql-router
channel: 8.0/stable
cinder-ceph:
charm: cinder-ceph
channel: 2024.1/stable
# =====================================================================
# Ceph: mon + osd + radosgw (Squid release per D-005)
# =====================================================================
ceph-mon:
charm: ceph-mon
channel: squid/stable
num_units: 3
to: [lxd:8, lxd:9, lxd:10]
options:
source: *ceph-source
expected-osd-count: 4
monitor-count: 3
bindings: *internal-bindings # Ceph 'public' here = clients on metal, NOT OS public API
constraints: arch=amd64
ceph-osd:
charm: ceph-osd
channel: squid/stable
num_units: 4
to: ["8", "9", "10", "11"]
options:
source: *ceph-source
osd-devices: /dev/vdb # libvirt-attached, MAAS-untracked, wiped 2026-05-22
bindings: *internal-bindings
constraints: arch=amd64 tags=openstack
storage: # Loop-backed auxiliaries (testcloud has no real SSDs)
bluestore-db: loop,1024M
bluestore-wal: loop,1024M
cache-devices: loop,10240M
osd-devices: loop,1024M
osd-journals: loop,1024M # Legacy storage name still in squid metadata; benign
ceph-radosgw:
charm: ceph-radosgw
channel: squid/stable
num_units: 1
to: [lxd:8]
options:
source: *ceph-source
# TODO(netbox): vip + ceph-radosgw-hacluster + :ha relation
bindings: *api-bindings # radosgw IS externally-facing (S3/Swift API)
constraints: arch=amd64
# =====================================================================
# Dashboard: openstack-dashboard (Horizon)
# =====================================================================
openstack-dashboard:
charm: openstack-dashboard
channel: 2024.1/stable
num_units: 1
to: [lxd:10]
options:
debug: "false"
# TODO(netbox): vip + openstack-dashboard-hacluster + :ha relation
bindings: *api-bindings
constraints: arch=amd64
dashboard-mysql-router:
charm: mysql-router
channel: 8.0/stable
# =====================================================================
# Load Balancer: Octavia
# =====================================================================
# CRITICAL: vault:certificates must be in bundle from day-one (post-deploy add
# causes documented apache2/octavia-api masking bug — see test deployment v3 handoff)
octavia:
charm: octavia
channel: 2024.1/stable
num_units: 1
to: [lxd:11]
options:
debug: false
openstack-origin: *openstack-origin
# ----- PKI material (4 cert blobs + passphrase) ---------------------
# TODO(octavia-cert): inline values BEFORE deploy. Two sources:
# (a) Copy from Bobcat backup at:
# ~/backups/pre-caracal-destroy-2026-05-22/bundle-pre-destroy.yaml
# (lines ~230-234; CA valid until 2027-05-15 — adequate for testcloud)
# (b) Generate fresh via the (yet-to-be-written) octavia-cert-runbook
# — required for Roosevelt deploy
# lb-mgmt-controller-cacert: <base64 PEM>
# lb-mgmt-controller-cert: <base64 PEM cert + key>
# lb-mgmt-issuing-ca-key-passphrase: <passphrase string>
# lb-mgmt-issuing-ca-private-key: <base64 encrypted PEM>
# lb-mgmt-issuing-cacert: <base64 PEM>
# TODO(netbox): vip + octavia-hacluster + :ha relation
bindings: *api-bindings
constraints: arch=amd64
octavia-mysql-router:
charm: mysql-router
channel: 8.0/stable
octavia-dashboard:
charm: octavia-dashboard
channel: 2024.1/stable
octavia-diskimage-retrofit:
charm: octavia-diskimage-retrofit
channel: 2024.1/stable
options:
amp-image-tag: octavia-amphora
# =====================================================================
# Secrets: Barbican
# =====================================================================
barbican:
charm: barbican
channel: 2024.1/stable
num_units: 1
to: [lxd:11]
options:
openstack-origin: *openstack-origin
# TODO(netbox): vip + barbican-hacluster + :ha relation
bindings: *api-bindings
constraints: arch=amd64
barbican-mysql-router:
charm: mysql-router
channel: 8.0/stable
barbican-vault:
charm: barbican-vault
channel: 2024.1/stable
# =====================================================================
# Kubernetes-as-a-Service: Magnum (Layer A — CAPI graft is Layer B)
# =====================================================================
# NOTE: After bundle deploys, magnum/0 will show active/idle but CANNOT
# create K8s clusters. Layer B (post-deploy) brings it to life:
# 1. capi-mgmt VM with k3s + CAPI operators (runbook 04a)
# 2. pip install magnum-capi-helm==1.1.0 into magnum venv (runbook 05)
# 3. /etc/magnum/magnum.conf.d/99-capi.conf with enabled_drivers
# 4. Install kubeconfig at /etc/magnum/kubeconfig
# 5. Create Keystone capi-mgmt project + capo user + app credential
magnum:
charm: magnum
channel: 2024.1/stable
num_units: 1
to: [lxd:9]
options:
openstack-origin: *openstack-origin
region: RegionOne
# TODO(netbox): vip + magnum-hacluster + :ha relation
bindings: *api-bindings
constraints: arch=amd64
magnum-mysql-router:
charm: mysql-router
channel: 8.0/stable
magnum-dashboard:
charm: magnum-dashboard
channel: 2024.1/stable
# =====================================================================
# DNS: Designate (NEW for Caracal v1 per D-008)
# =====================================================================
# Naming convention: <service>.omega.dc0.vr0.cloud.neumatrix.local
designate:
charm: designate
channel: 2024.1/stable
num_units: 1
to: [lxd:8]
options:
openstack-origin: *openstack-origin
# TODO(d008): set nameservers per omega.dc0.vr0 zone before deploy
# nameservers: "ns1.omega.dc0.vr0.cloud.neumatrix.local. ns2.omega.dc0.vr0.cloud.neumatrix.local."
# TODO(netbox): vip + designate-hacluster + :ha relation
bindings: *api-bindings
constraints: arch=amd64
designate-mysql-router:
charm: mysql-router
channel: 8.0/stable
designate-bind:
charm: designate-bind
channel: 2024.1/stable
num_units: 1
to: [lxd:8]
bindings: *internal-bindings
constraints: arch=amd64
# =====================================================================
# HA Cluster Subordinates (COMMENTED until NetBox VIP allocations)
# =====================================================================
# Channel: 2.4/stable (per Caracal Charm Delivery table, corrected from D-002).
# Uncomment EACH block (hacluster app + corresponding :ha relation + principal vip)
# ATOMICALLY when its VIP is allocated. 13 hacluster subordinates total per D-009.
#
# keystone-hacluster: { charm: hacluster, channel: 2.4/stable }
# glance-hacluster: { charm: hacluster, channel: 2.4/stable }
# neutron-api-hacluster: { charm: hacluster, channel: 2.4/stable }
# nova-cloud-controller-hacluster: { charm: hacluster, channel: 2.4/stable }
# placement-hacluster: { charm: hacluster, channel: 2.4/stable }
# openstack-dashboard-hacluster: { charm: hacluster, channel: 2.4/stable }
# cinder-hacluster: { charm: hacluster, channel: 2.4/stable }
# octavia-hacluster: { charm: hacluster, channel: 2.4/stable }
# barbican-hacluster: { charm: hacluster, channel: 2.4/stable }
# magnum-hacluster: { charm: hacluster, channel: 2.4/stable }
# vault-hacluster: { charm: hacluster, channel: 2.4/stable }
# ceph-radosgw-hacluster: { charm: hacluster, channel: 2.4/stable }
# designate-hacluster: { charm: hacluster, channel: 2.4/stable }
relations:
# ---- Vault HA backend chain (NEW for Caracal v1; chicken-and-egg via easyrsa)
- [easyrsa:client, etcd:certificates] # easyrsa issues etcd TLS one-time
- [vault:etcd, etcd:db] # vault uses etcd as HA backend
- [vault-mysql-router:db-router, mysql-innodb-cluster:db-router]
- [vault:shared-db, vault-mysql-router:shared-db]
- [mysql-innodb-cluster:certificates, vault:certificates]
# TODO(netbox): - [vault:ha, vault-hacluster:ha]
# ---- Keystone (identity, hub of all OS service relations)
- [keystone-mysql-router:db-router, mysql-innodb-cluster:db-router]
- [keystone-mysql-router:shared-db, keystone:shared-db]
- [keystone:certificates, vault:certificates]
# TODO(netbox): - [keystone:ha, keystone-hacluster:ha]
# ---- Glance (image)
- [glance-mysql-router:db-router, mysql-innodb-cluster:db-router]
- [glance-mysql-router:shared-db, glance:shared-db]
- [glance:identity-service, keystone:identity-service]
- [glance:certificates, vault:certificates]
# TODO(netbox): - [glance:ha, glance-hacluster:ha]
# ---- Glance simplestreams sync (Octavia amphora pipeline source)
- [glance-simplestreams-sync:identity-service, keystone:identity-service]
- [glance-simplestreams-sync:certificates, vault:certificates]
# ---- Nova cloud controller (NCC)
- [ncc-mysql-router:db-router, mysql-innodb-cluster:db-router]
- [ncc-mysql-router:shared-db, nova-cloud-controller:shared-db]
- [nova-cloud-controller:identity-service, keystone:identity-service]
- [nova-cloud-controller:amqp, rabbitmq-server:amqp]
- [nova-cloud-controller:image-service, glance:image-service]
- [nova-cloud-controller:neutron-api, neutron-api:neutron-api]
- [nova-cloud-controller:cloud-compute, nova-compute:cloud-compute]
- [nova-cloud-controller:cinder-volume-service, cinder:cinder-volume-service]
- [nova-cloud-controller:certificates, vault:certificates]
# TODO(netbox): - [nova-cloud-controller:ha, nova-cloud-controller-hacluster:ha]
# ---- Nova compute
- [nova-compute:amqp, rabbitmq-server:amqp]
- [nova-compute:image-service, glance:image-service]
# ---- Placement
- [placement-mysql-router:db-router, mysql-innodb-cluster:db-router]
- [placement-mysql-router:shared-db, placement:shared-db]
- [placement:identity-service, keystone:identity-service]
- [placement:placement, nova-cloud-controller:placement]
- [placement:certificates, vault:certificates]
# TODO(netbox): - [placement:ha, placement-hacluster:ha]
# ---- Neutron API + OVN
- [neutron-api-mysql-router:db-router, mysql-innodb-cluster:db-router]
- [neutron-api-mysql-router:shared-db, neutron-api:shared-db]
- [neutron-api:identity-service, keystone:identity-service]
- [neutron-api:amqp, rabbitmq-server:amqp]
- [neutron-api:certificates, vault:certificates]
- [neutron-api-plugin-ovn:neutron-plugin, neutron-api:neutron-plugin-api-subordinate]
- [neutron-api-plugin-ovn:ovsdb-cms, ovn-central:ovsdb-cms]
- [neutron-api-plugin-ovn:certificates, vault:certificates]
- [ovn-central:certificates, vault:certificates]
- [ovn-chassis:ovsdb, ovn-central:ovsdb]
- [ovn-chassis:nova-compute, nova-compute:neutron-plugin]
- [ovn-chassis:certificates, vault:certificates]
# TODO(netbox): - [neutron-api:ha, neutron-api-hacluster:ha]
# ---- Cinder + cinder-ceph
- [cinder-mysql-router:db-router, mysql-innodb-cluster:db-router]
- [cinder-mysql-router:shared-db, cinder:shared-db]
- [cinder:identity-service, keystone:identity-service]
- [cinder:amqp, rabbitmq-server:amqp]
- [cinder:image-service, glance:image-service]
- [cinder:certificates, vault:certificates]
- [cinder-ceph:storage-backend, cinder:storage-backend]
- [cinder-ceph:ceph, ceph-mon:client]
- [cinder-ceph:ceph-access, nova-compute:ceph-access]
# TODO(netbox): - [cinder:ha, cinder-hacluster:ha]
# ---- Ceph mon + osd + radosgw
- [ceph-mon:osd, ceph-osd:mon]
- [ceph-mon:client, nova-compute:ceph]
- [ceph-mon:client, glance:ceph]
- [ceph-radosgw:mon, ceph-mon:radosgw]
- [ceph-radosgw:identity-service, keystone:identity-service]
- [ceph-radosgw:certificates, vault:certificates]
# TODO(netbox): - [ceph-radosgw:ha, ceph-radosgw-hacluster:ha]
# ---- OpenStack Dashboard (Horizon)
- [dashboard-mysql-router:db-router, mysql-innodb-cluster:db-router]
- [dashboard-mysql-router:shared-db, openstack-dashboard:shared-db]
- [openstack-dashboard:identity-service, keystone:identity-service]
- [openstack-dashboard:certificates, vault:certificates]
# TODO(netbox): - [openstack-dashboard:ha, openstack-dashboard-hacluster:ha]
# ---- Octavia (LBaaS)
# CRITICAL: octavia:certificates ↔ vault:certificates MUST be present at deploy time
- [octavia-mysql-router:db-router, mysql-innodb-cluster:db-router]
- [octavia-mysql-router:shared-db, octavia:shared-db]
- [octavia:identity-service, keystone:identity-service]
- [octavia:amqp, rabbitmq-server:amqp]
- [octavia:neutron-api, neutron-api:neutron-load-balancer]
- [octavia:certificates, vault:certificates]
- [octavia-dashboard:dashboard, openstack-dashboard:dashboard-plugin]
- [ovn-chassis-octavia:ovsdb, ovn-central:ovsdb]
- [ovn-chassis-octavia:ovsdb-subordinate, octavia:ovsdb-subordinate]
- [ovn-chassis-octavia:certificates, vault:certificates]
# Octavia amphora image pipeline
- [octavia-diskimage-retrofit:juju-info, glance-simplestreams-sync:juju-info]
- [octavia-diskimage-retrofit:identity-credentials, keystone:identity-credentials]
# TODO(netbox): - [octavia:ha, octavia-hacluster:ha]
# ---- Barbican (secrets)
- [barbican-mysql-router:db-router, mysql-innodb-cluster:db-router]
- [barbican-mysql-router:shared-db, barbican:shared-db]
- [barbican:identity-service, keystone:identity-service]
- [barbican:amqp, rabbitmq-server:amqp]
- [barbican:certificates, vault:certificates]
- [barbican:secrets, barbican-vault:secrets]
- [barbican-vault:certificates, vault:certificates]
- [barbican-vault:secrets-storage, vault:secrets]
# TODO(netbox): - [barbican:ha, barbican-hacluster:ha]
# ---- Magnum (Layer A only; CAPI graft is Layer B/runbook 05)
- [magnum-mysql-router:db-router, mysql-innodb-cluster:db-router]
- [magnum:shared-db, magnum-mysql-router:shared-db]
- [magnum:identity-service, keystone:identity-service]
- [magnum:amqp, rabbitmq-server:amqp]
- [magnum:certificates, vault:certificates]
- [magnum-dashboard:dashboard, openstack-dashboard:dashboard-plugin]
# TODO(netbox): - [magnum:ha, magnum-hacluster:ha]
# ---- Designate (DNS) — NEW for Caracal v1 per D-008
- [designate-mysql-router:db-router, mysql-innodb-cluster:db-router]
- [designate-mysql-router:shared-db, designate:shared-db]
- [designate:identity-service, keystone:identity-service]
- [designate:amqp, rabbitmq-server:amqp]
- [designate:certificates, vault:certificates]
- [designate:dns-backend, designate-bind:dns-backend]
# TODO(netbox): - [designate:ha, designate-hacluster:ha]