Files
rollcall/deploy/install-rack.sh
T
Ilker ManapandClaude Opus 5.5 736a7e38a3
CI / agent (push) Successful in 3s
CI / site (push) Successful in 2s
CI / go (push) Successful in 32s
Network model, IPAM, interface layouts and the region/rack split (MAAS-style)
- fabrics, VLANs, subnets, IP ranges (dynamic/reserved/static), IPAM with adoption of
  addresses machines already have; rollcall fabric|vlan|subnet|range|ip
- interface layouts (physical/bond/vlan, NICs by selector: boot, name, mac, fastest:N, ib:N)
  per machine or per tag; deployment allocates addresses and writes cloud-init network-config
  plus udev name rules (RHEL cloud images boot with net.ifnames=0); release frees them;
  rollcall layout, rollcall net show|set
- region/rack: rollcall rack long-polls its desired state (per-MAC PXE files kept in the
  database, dnsmasq configuration and host files) and a BMC command queue, caches boot and OS
  images (kernels/initrds prefetched for TFTP), proxies the node API and tags requests with its
  name; the region runs an embedded rack controller; install-rack.sh, rollcall-rack.service
- dnsmasq configuration generated per rack from the VLANs it serves (split pool for two racks);
  reload script restarts only on change and restores the last working config if dnsmasq does
  not come back (drilled in the lab)
- web: Network page, per-machine network tab, layout action, tag layout; console: Network page,
  network section in the machine view, layout action
- tests for candidates, plans (default, bond+VLAN, pinned, DHCP fallback), network-config,
  udev rules and dnsmasq rendering
- lab: pve-vbmc address script finds the interface per BMC address

Verified in the lab: embedded rack (10.213.77.0/24) and a remote rack controller on a second
SDN segment (10.213.78.0/24): enlistment, commissioning, BMC through the rack's queue, image
cache, deployment and phone-home through the rack; Debian 13, Ubuntu 24.04 and Rocky 9 with a
static boot NIC and with an active-backup bond carrying VLAN 200.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 23:58:40 +01:00

57 lines
3.3 KiB
Bash

#!/bin/sh
# Install a rollcall rack controller on this host (Debian/Ubuntu). Run as root
# from this directory with the rollcall binary next to it and
# /etc/rollcall/rack.json written (see rack.example.json). The region needs a
# rack_secret in its config.json; the same value goes into rack.json.
#
# The rack controller serves DHCP/TFTP (dnsmasq) on the VLANs the region
# assigns to it, keeps boot and OS images in a local cache, runs BMC commands
# and passes the node API through to the region.
set -eu
cd "$(dirname "$0")"
[ -r /etc/rollcall/rack.json ] || { echo "write /etc/rollcall/rack.json first (see rack.example.json)" >&2; exit 1; }
export DEBIAN_FRONTEND=noninteractive
apt-get install -y -q dnsmasq ipmitool pxelinux syslinux-common syslinux-efi jq >/dev/null
getent passwd rollcall >/dev/null || useradd --system --no-create-home --shell /usr/sbin/nologin --user-group rollcall
[ -x ./rollcall ] && install -m 0755 rollcall /usr/local/bin/rollcall
chgrp rollcall /etc/rollcall/rack.json && chmod 0640 /etc/rollcall/rack.json
TFTP=$(jq -r '.tftp_root // "/srv/tftp"' /etc/rollcall/rack.json)
CACHE=$(jq -r '.cache_dir // "/var/cache/rollcall"' /etc/rollcall/rack.json)
DNS=$(jq -r '.dnsmasq_dir // "/var/lib/rollcall/dnsmasq"' /etc/rollcall/rack.json)
# image cache: kernels/initrds are prefetched (TFTP cannot fetch on demand), the rest fills on first use
install -d -o rollcall -g rollcall "$CACHE" "$CACHE/rollcall" "$CACHE/images" "$CACHE/os"
# TFTP root: syslinux for BIOS and UEFI, per-MAC files written by the rack controller
install -d "$TFTP" "$TFTP/efi64"
install -d -o rollcall -g rollcall -m 2775 "$TFTP/pxelinux.cfg"
cp /usr/lib/PXELINUX/pxelinux.0 "$TFTP/"
for f in ldlinux.c32 menu.c32 libutil.c32 libcom32.c32 poweroff.c32; do cp /usr/lib/syslinux/modules/bios/$f "$TFTP/"; done
cp /usr/lib/SYSLINUX.EFI/efi64/syslinux.efi "$TFTP/efi64/"
for f in ldlinux.e64 menu.c32 libutil.c32 libcom32.c32; do cp /usr/lib/syslinux/modules/efi64/$f "$TFTP/efi64/"; done
ln -sfn ../pxelinux.cfg "$TFTP/efi64/pxelinux.cfg"
ln -sfn "$CACHE/rollcall" "$TFTP/rollcall"
ln -sfn "$CACHE/images" "$TFTP/images"
ln -sfn ../rollcall "$TFTP/efi64/rollcall"
ln -sfn ../images "$TFTP/efi64/images"
# dnsmasq reads what the rack controller generates; until then it only answers local DNS
install -d -o rollcall -g rollcall "$DNS" "$DNS/conf.d"
for f in hosts hosts.dhcp; do [ -e "$DNS/$f" ] || install -m 0644 -o rollcall -g rollcall /dev/null "$DNS/$f"; done
# bind-dynamic binds address by address, so systemd-resolved's 127.0.0.53 stub does not get in the way;
# until the region assigns a VLAN only loopback is served
printf '# rollcall rack controller: the configuration is generated from the region'"'"'s network model\nbind-dynamic\ninterface=lo\nconf-dir=%s/conf.d/,*.conf\n' "$DNS" > /etc/dnsmasq.d/rollcall.conf
install -m 0755 rollcall-dnsmasq-reload.sh /usr/local/bin/rollcall-dnsmasq-reload.sh
install -m 0644 rollcall-dnsmasq.path rollcall-dnsmasq.service rollcall-rack.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable dnsmasq.service rollcall-dnsmasq.path >/dev/null 2>&1
systemctl restart dnsmasq.service || { journalctl -u dnsmasq -n 5 --no-pager >&2; exit 1; }
systemctl start rollcall-dnsmasq.path
systemctl enable --now rollcall-rack.service
systemctl restart rollcall-rack.service
sleep 2
systemctl --no-pager status rollcall-rack.service | head -5