Newer
Older
openstack-caracal-ipv4 / bundle.yaml
@JANeumatrix JANeumatrix 18 hours ago 23 KB Updates
# ============================================================
# 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:
      vip: 10.12.4.236
      os-public-hostname: vault.omega.dc0.vr0.cloud.neumatrix.local
    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:
      vip: 10.12.4.229
      os-public-hostname: keystone.omega.dc0.vr0.cloud.neumatrix.local
    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:
      vip: 10.12.4.228
      os-public-hostname: glance.omega.dc0.vr0.cloud.neumatrix.local
    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
      vip: 10.12.4.232
      os-public-hostname: nova.omega.dc0.vr0.cloud.neumatrix.local
    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:
      vip: 10.12.4.235
      os-public-hostname: placement.omega.dc0.vr0.cloud.neumatrix.local
    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
      vip: 10.12.4.231
      os-public-hostname: neutron.omega.dc0.vr0.cloud.neumatrix.local
    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
      vip: 10.12.4.226
      os-public-hostname: cinder.omega.dc0.vr0.cloud.neumatrix.local
    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
      # v2-deferred: ceph-radosgw HA deferred to v2 per workstream-2 decision.
      # vip slot 10.12.4.225 reserved for ceph-radosgw VIP in v2.
      # See also commented ceph-radosgw-hacluster app + :ha relation below.
    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"
      vip: 10.12.4.234
      os-public-hostname: horizon.omega.dc0.vr0.cloud.neumatrix.local
    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 -------------------------------------------------
      # 5 lb-mgmt-* options are supplied via overlays/octavia-pki.yaml
      # (gitignored). Generated per runbooks/01a-octavia-pki-generation.md.
      # Deploy with:
      #   juju deploy ./bundle.yaml \
      #     --overlay overlays/vr0-dc0-testcloud.yaml \
      #     --overlay overlays/octavia-pki.yaml
      vip: 10.12.4.233
      os-public-hostname: octavia.omega.dc0.vr0.cloud.neumatrix.local
    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
      vip: 10.12.4.224
      os-public-hostname: barbican.omega.dc0.vr0.cloud.neumatrix.local
    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
      vip: 10.12.4.230
      os-public-hostname: magnum.omega.dc0.vr0.cloud.neumatrix.local
    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."
      vip: 10.12.4.227
      os-public-hostname: designate.omega.dc0.vr0.cloud.neumatrix.local
    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 (12 active for v1; ceph-radosgw deferred to v2)
  # =====================================================================
  # Channel: 2.4/stable (per Caracal Charm Delivery table, D-002 verified 2026-05-22).
  # VIPs allocated from provider /22 range 10.12.4.224-.254 per D-003.
  # NetBox IPAddress records queued post-deployment (engineer review pending).
  # See workstream-2 decision (2026-05-22).
  #
  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 }
  # v2-deferred: 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]
  - [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]
  - [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]
  - [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]
  - [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]
  - [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]
  - [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]
  - [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]
  # v2-deferred: - [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]
  - [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]
  - [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]
  - [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]
  - [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]
  - [designate:ha, designate-hacluster:ha]