feat(templates): install ci-static-ip/ci-report-ip via Prepare+Install scripts

Windows (Prepare-WinBuild2025/2022): read ci-static-ip.ps1 from
guest-setup/windows/ on the host, push content over WinRM, register the
CI-StaticIp scheduled task (AtStartup/SYSTEM). Adds StaticIpTask and
StaticIpScript post-setup assertions.

Linux (Install-CIToolchain-Linux2404.sh): embed ci-report-ip.sh and
ci-report-ip.service content inline via heredoc tee, replacing the broken
cp-from-relative-path approach (the script runs inside the VM where the
host-side guest-setup/ directory does not exist).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 00:37:07 +02:00
parent 1bc3ec601c
commit 41a0a113df
3 changed files with 173 additions and 21 deletions
+97 -3
View File
@@ -174,12 +174,106 @@ assert_step "99-ci-dhcp-allnics.yaml exists" test -f /etc/netplan/99-ci-dhcp-all
# Static (ip_pool): reads guestinfo.ip-assignment injected by the host
# orchestrator, applies static NIC config, reports back.
# DHCP fallback: waits for DHCP address, reports via guestinfo.ci-ip.
# The script and service are sourced from template/guest-setup/linux/.
# Content embedded inline — this script runs inside the VM where the host-side
# template/guest-setup/linux/ directory is not present.
echo ""
echo "=== Step 7b: CI IP reporter (with static IP support) ==="
sudo cp "$(dirname "$0")/guest-setup/linux/ci-report-ip.sh" /usr/local/bin/ci-report-ip.sh
sudo tee /usr/local/bin/ci-report-ip.sh > /dev/null << 'EOREPORTIP'
#!/bin/bash
# CI VM IP reporter — called by ci-report-ip.service at boot.
#
# Supports two modes:
# Static (ip_pool): reads guestinfo.ip-assignment injected by the host
# orchestrator, applies static NIC config, reports back.
# DHCP fallback: waits for DHCP address, reports via guestinfo.ci-ip.
#
# The VMCI channel (vmware-rpctool) does not require TCP/IP to be initialised —
# it communicates via the VMware virtual hardware interface. This means the
# static IP can be configured before network-online.target, so by the time SSH
# starts listening the NIC already has the correct address.
RPCTOOL=/usr/bin/vmware-rpctool
[ -x "$RPCTOOL" ] || exit 0
# ── Check for pre-assigned IP from orchestrator ───────────────────────────────
assigned_ip=$("$RPCTOOL" "info-get guestinfo.ip-assignment" 2>/dev/null | tr -d '[:space:]')
if [[ "$assigned_ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
netmask=$("$RPCTOOL" "info-get guestinfo.netmask" 2>/dev/null | tr -d '[:space:]')
gateway=$("$RPCTOOL" "info-get guestinfo.gateway" 2>/dev/null | tr -d '[:space:]')
# Resolve primary NIC (first non-loopback).
iface=$(ip -o link show | awk -F': ' '$2 != "lo" {print $2; exit}')
if [ -z "$iface" ]; then
echo "ci-report-ip: no non-loopback interface found" | systemd-cat -t ci-report-ip
exit 1
fi
# Compute prefix length from netmask (default /24).
prefix=24
if [ -n "$netmask" ]; then
prefix=$(python3 -c \
"import ipaddress; print(ipaddress.IPv4Network('0.0.0.0/$netmask',strict=False).prefixlen)" \
2>/dev/null) || prefix=24
fi
# Flush any existing config (DHCP or stale static) and apply.
ip addr flush dev "$iface" 2>/dev/null || true
ip addr add "${assigned_ip}/${prefix}" dev "$iface"
ip link set "$iface" up
if [[ "$gateway" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
ip route add default via "$gateway" dev "$iface" 2>/dev/null || true
fi
# Report IP back to host via guestinfo.ci-ip.
"$RPCTOOL" "info-set guestinfo.ci-ip $assigned_ip" 2>/dev/null
echo "ci-report-ip: applied static IP $assigned_ip/$prefix via guestinfo" \
| systemd-cat -t ci-report-ip
exit 0
fi
# ── Fallback: DHCP — wait for IP and report ───────────────────────────────────
# Retries for up to 60 s to tolerate open-vm-tools re-init after UUID change
# (linked clones get a new UUID — vmware-rpctool may fail briefly on first boot).
for i in $(seq 1 30); do
IP=$(ip -4 route get 1.0.0.0 2>/dev/null \
| awk '{for(i=1;i<=NF;i++) if($i=="src") print $(i+1)}' \
| head -1)
if [ -n "$IP" ]; then
if "$RPCTOOL" "info-set guestinfo.ci-ip $IP" 2>/dev/null; then
echo "ci-report-ip: set guestinfo.ci-ip=$IP via DHCP (attempt $i)" \
| systemd-cat -t ci-report-ip
exit 0
fi
fi
sleep 2
done
echo "ci-report-ip: failed to set guestinfo.ci-ip after 30 attempts" \
| systemd-cat -t ci-report-ip
exit 1
EOREPORTIP
sudo chmod +x /usr/local/bin/ci-report-ip.sh
sudo cp "$(dirname "$0")/guest-setup/linux/ci-report-ip.service" /etc/systemd/system/ci-report-ip.service
sudo tee /etc/systemd/system/ci-report-ip.service > /dev/null << 'EOSERVICE'
[Unit]
Description=Report CI VM IP to VMware host via guestinfo
# Run after open-vm-tools so vmware-rpctool is available.
# Do NOT add network-online.target — we want to run BEFORE the network stack
# settles so static IP is applied before SSH/other services start.
After=open-vm-tools.service
Wants=open-vm-tools.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/ci-report-ip.sh
RemainAfterExit=yes
TimeoutStartSec=120
[Install]
WantedBy=multi-user.target
EOSERVICE
sudo systemctl daemon-reload
sudo systemctl enable ci-report-ip.service