diff --git a/scripts/lib-hosts.sh b/scripts/lib-hosts.sh index 3cc0dd9..46dbba5 100644 --- a/scripts/lib-hosts.sh +++ b/scripts/lib-hosts.sh @@ -43,6 +43,27 @@ # Mirrors the surviving juju/lxd/tailscale virsh machines' live config (read # 2026-06-26). power_id is set per host to the hostname by the caller. VIRSH_POWER_ADDRESS="qemu+ssh://logxen@10.12.64.1/system" +# VR1 NODE NIC -> PLANE ORDER (MEASURED 2026-07-30; D-133 flat per-NIC carve). +# The substrate roots pin six MACs per node, and the module attaches them in list +# order, so macs[i] IS enps0. Verified end-to-end on vr1-dc0-control-01: +# main.tf macs[0..5] = be:69:c5, 29:e5:2b, 05:98:c4, 96:e8:36, 5a:dc:91, 35:cc:01 +# live carve = enp1s0 be:69:c5 metal-admin (fabric-4, PXE) +# enp2s0 29:e5:2b provider-public (br-ex inherits this MAC) +# enp3s0 05:98:c4 metal-internal +# enp4s0 96:e8:36 data-tenant +# enp5s0 5a:dc:91 storage +# enp6s0 35:cc:01 replication +# +# !! THIS IS NOT lib-net.sh's PLANE_CIDRS ORDER. !! PLANE_CIDRS starts with +# provider-public; the NIC order starts with METAL-ADMIN. Anything that walks +# PLANE_CIDRS positionally to assign NICs swaps enp1s0 and enp2s0 and puts the +# PXE/metal-admin leg on provider-public -- which would strand commissioning on a +# plane with no DHCP. Iterate THIS array for NIC placement, never PLANE_CIDRS. +NIC_PLANE_ORDER=( metal-admin provider-public metal-internal data-tenant storage replication ) +# The provider-public NIC is the OVS br-ex parent (Pattern A): the node's static +# lands on br-ex, and the member NIC itself carries no L3 link. +BREX_PARENT_NIC="enp2s0" + # The per-region forms exist only for the VR1 DCs (D-132 q1). Declared EMPTY at # the flat/VR0 layer so a shell that never selects a VR1 DC cannot pick up a # neighbouring DC's address -- an empty value fails loud; a stale one powers off diff --git a/tests/dc-selector/run-tests.sh b/tests/dc-selector/run-tests.sh index bf413e3..2ac5d5e 100644 --- a/tests/dc-selector/run-tests.sh +++ b/tests/dc-selector/run-tests.sh @@ -249,6 +249,29 @@ H0_N="$(lib_hosts_select_dc vr1-dc0 >/dev/null 2>&1; echo "${#HOSTS[@]}")" chk "hosts vr1-dc0 fleet count 10 (D-121 Option C 9 role + D-104 juju-01)" "$H0_N" "10" +# --- VR1 NODE NIC -> PLANE ORDER (MEASURED 2026-07-30) --------------------- +# macs[i] in the substrate root IS enps0, verified against the live carve on +# vr1-dc0-control-01. The load-bearing assertion is the LAST one: this order is +# NOT PLANE_CIDRS order, and anything that walks PLANE_CIDRS positionally to +# place NICs puts the PXE/metal-admin leg on provider-public -- stranding +# commissioning on a plane with no DHCP. +chk "nic order [0] is metal-admin (the PXE leg)" "${NIC_PLANE_ORDER[0]}" "metal-admin" +chk "nic order [1] is provider-public" "${NIC_PLANE_ORDER[1]}" "provider-public" +chk "nic order [5] is replication" "${NIC_PLANE_ORDER[5]}" "replication" +chk "nic order has six entries" "${#NIC_PLANE_ORDER[@]}" "6" +chk "br-ex parent NIC is enp2s0 (provider-public)" "$BREX_PARENT_NIC" "enp2s0" +# every NIC-order entry must be a real space name +NIC_BAD=0 +for _n in "${NIC_PLANE_ORDER[@]}"; do + _found=0; for _s in "${SPACES6[@]}"; do [ "$_n" = "$_s" ] && _found=1; done + [ "$_found" = 1 ] || NIC_BAD=$((NIC_BAD+1)) +done +chk "every nic-order entry is one of the six spaces" "$NIC_BAD" "0" +# THE TRAP ASSERTION: the two orders must DIFFER at position 0. +NIC0="${NIC_PLANE_ORDER[0]}"; PC0="${PLANE_NAME[${PLANE_CIDRS[0]}]}" +[ "$NIC0" != "$PC0" ] && ok "nic order DIFFERS from PLANE_CIDRS order at [0] (the enp1s0/enp2s0 trap)" \ + || no "nic order DIFFERS from PLANE_CIDRS order at [0] -- both read '$NIC0', so the trap guard is vacuous" + # --- ONE SELECTION PER SHELL (stale cross-DC guard, lib-net precedent) --- ( lib_hosts_select_dc vr1-dc0 >/dev/null 2>&1; lib_hosts_select_dc vr1-dc1 2>/dev/null ); \ chk "hosts dc0->dc1 re-select REFUSED (stale cross-DC values)" "$?" 1