diff --git a/docs/TODO.md b/docs/TODO.md index 5908aa1..4bb9f97 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -143,10 +143,14 @@ boot LAN. `/etc/nvme/discovery.conf` correctly, but `initqueue/online/` is **empty** — no autoconnect hook is registered, so `nvme connect-all` is never run (no attempt in dmesg) and the namespace never appears. Drivers load and - `/dev/nvme-fabrics` exists; only the connect trigger is missing. **Fixed:** - `dot1x-macsec-up.sh` (rd.dot1x=0 branch) now parses the discover address and - queues `nvme connect-all` on the initqueue itself (retries until the - namespace shows up). **⚠ The secure path has the same dependency on the + `/dev/nvme-fabrics` exists; only the connect trigger is missing. A job + placed on the *main* initqueue from a settled hook gets registered but is + **never re-executed** once the loop blocks on udev events (verified: job + present, manual `connect-all` works, namespace stays absent). **Fixed:** a + dedicated `initqueue/online` hook (`nvmf-connect.sh`, installed via + `inst_hook initqueue/online 90`) runs `nvme connect-all` when network-legacy + sources online hooks on DHCP-bound — the event-driven trigger the nvmf + module omits. **⚠ The secure path has the same dependency on the (absent) nvmf autoconnect** — when 802.1X is re-enabled, the macsec0 path must likewise drive `connect-all` (or the network-manager port #1 must wire a working autoconnect). Currently only the test path is fixed. diff --git a/files/dracut/95dot1x-macsec/dot1x-macsec-up.sh b/files/dracut/95dot1x-macsec/dot1x-macsec-up.sh index 5121bb6..5286247 100755 --- a/files/dracut/95dot1x-macsec/dot1x-macsec-up.sh +++ b/files/dracut/95dot1x-macsec/dot1x-macsec-up.sh @@ -59,25 +59,12 @@ if [ "$(getarg rd.dot1x=)" = "0" ]; then info "dot1x-macsec: test hostnqn $(cat /etc/nvme/hostnqn)" fi - # Drive the NVMe-oF connect ourselves. This distro's dracut `nvmf` module - # parses rd.nvmf.discover into /etc/nvme/discovery.conf but registers NO - # initqueue/online autoconnect hook (that hook dir is empty), so - # `nvme connect-all` is never run, the root namespace never appears, and the - # boot spins on /dev/mapper/root forever. Queue connect-all on the main - # initqueue so it retries each loop until the namespace shows up (the link - # is already up via ip=dhcp; connect-all is idempotent once connected). - _disc=$(getarg rd.nvmf.discover=) # e.g. tcp,192.168.50.10,4420 - if [ -n "$_disc" ]; then - _trtype=${_disc%%,*} # tcp - _rest=${_disc#*,} # 192.168.50.10,4420 - _traddr=${_rest%%,*} # 192.168.50.10 - _trsvcid=${_rest##*,} # 4420 - info "dot1x-macsec: queueing nvme connect-all ${_trtype}/${_traddr}/${_trsvcid}" - /sbin/initqueue --unique --name nvmf-connect-all \ - nvme connect-all -t "$_trtype" -a "$_traddr" -s "$_trsvcid" - else - warn "dot1x-macsec: rd.nvmf.discover not set — cannot connect NVMe root" - fi + # The NVMe-oF connect is driven by the initqueue/online hook + # (nvmf-connect.sh), which fires when the ip=dhcp link comes online — the + # correct event-driven place. (A job queued on the MAIN initqueue from here + # is registered but never re-executed once the loop blocks on events, so it + # never connected; and this distro's nvmf module registers no online + # autoconnect of its own.) : > "$STAMP" exit 0 fi diff --git a/files/dracut/95dot1x-macsec/module-setup.sh b/files/dracut/95dot1x-macsec/module-setup.sh index 737b044..5f79641 100755 --- a/files/dracut/95dot1x-macsec/module-setup.sh +++ b/files/dracut/95dot1x-macsec/module-setup.sh @@ -42,5 +42,10 @@ install() { # Hook: runs from the initqueue once the NIC exists, before netroot inst_hook initqueue/settled 30 "$moddir/dot1x-macsec-up.sh" + # Test-mode (rd.dot1x=0) NVMe-oF connect, driven event-wise on link-up. + # This distro's nvmf module registers no autoconnect, and a main-initqueue + # job isn't re-run once the loop waits on events — so connect here instead. + inst_hook initqueue/online 90 "$moddir/nvmf-connect.sh" + dracut_need_initqueue } diff --git a/files/dracut/95dot1x-macsec/nvmf-connect.sh b/files/dracut/95dot1x-macsec/nvmf-connect.sh new file mode 100644 index 0000000..b35b5a0 --- /dev/null +++ b/files/dracut/95dot1x-macsec/nvmf-connect.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# nvmf-connect.sh — initqueue/online hook (fires when a NIC comes online). +# +# TEST MODE ONLY (rd.dot1x=0): drive the NVMe-oF root connect here. +# This distro's dracut `nvmf` module parses rd.nvmf.discover into +# /etc/nvme/discovery.conf but registers NO autoconnect hook (initqueue/online/ +# ships empty), and a job placed on the MAIN initqueue is not re-executed once +# the loop blocks waiting on udev events — so `nvme connect-all` otherwise never +# runs, the root namespace never appears, and boot spins on /dev/mapper/root +# forever. initqueue/online is the correct, event-driven place: network-legacy +# sources these hooks once DHCP is bound, so the link is guaranteed up here. +# Idempotent via a stamp; connect-all is itself safe to re-run, and on failure +# we leave the stamp unset so the next online event retries. +# +# The secure path (rd.dot1x unset/!=0) connects over macsec0 from its own flow +# in dot1x-macsec-up.sh and must NOT connect over the physical link here. + +type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh + +[ "$(getarg rd.dot1x=)" = "0" ] || exit 0 +[ -e /run/dot1x/.nvmf-connected ] && exit 0 + +_disc=$(getarg rd.nvmf.discover=) # e.g. tcp,192.168.50.10,4420 +[ -n "$_disc" ] || { warn "nvmf-connect: rd.nvmf.discover not set"; exit 0; } +_trtype=${_disc%%,*} +_rest=${_disc#*,} +_traddr=${_rest%%,*} +_trsvcid=${_rest##*,} + +# nvme_tcp is usually auto-loaded, but ensure it so connect-all can't fail on a +# missing /dev/nvme-fabrics. +modprobe nvme_tcp 2>/dev/null + +info "nvmf-connect: nvme connect-all ${_trtype}/${_traddr}/${_trsvcid}" +if nvme connect-all -t "$_trtype" -a "$_traddr" -s "$_trsvcid"; then + mkdir -p /run/dot1x + : > /run/dot1x/.nvmf-connected + info "nvmf-connect: connected — namespace + by-id link should appear shortly" +else + warn "nvmf-connect: connect-all failed; will retry on next online event" +fi +exit 0 diff --git a/serving/.env.example b/serving/.env.example index e9077aa..c5b26f5 100644 --- a/serving/.env.example +++ b/serving/.env.example @@ -1,7 +1,7 @@ # Copy to .env and edit for your test LAN/bridge, then: docker compose up -d # Release being served. Must match the Packer build (fleet-.efi). -IMAGE_VERSION=0.0.0-9841455 +IMAGE_VERSION=0.0.0-a508dce # OCI release-artifact image (built by scripts/build-oci.sh). Mounted directly # as a Docker image volume — the default artifact source. Pin by digest in @@ -10,7 +10,7 @@ OCI_IMAGE=git.bitasylum.org/audiobuzz/fleet-boot # Fallback only (Docker < 28 / offline): local Packer output dir, used by the # commented bind-mounts in docker-compose.yml. Ignored when image volumes work. -ARTIFACT_SRC=../artifacts/0.0.0-9841455 +ARTIFACT_SRC=../artifacts/0.0.0-a508dce # SPDK NVMe/TCP target image — prebuilt + pushed by CI # (.gitea/workflows/spdk-image.yaml); the serving host just pulls it.