a0c0fb114f
CI / Lint + build + test (push) Has been cancelled
vetting-agent gains a `host` subcommand that runs as a systemd service
installed by the quick-register one-liner, POSTing every 30s to
/api/v1/hosts/{mac}/heartbeat so the dashboard tile shows "online" or
"Nm ago" without waiting on WoL. Ships dormant client code for the
Phase 2 reboot_for_vetting command so the server can flip it on later
without a binary redeploy.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
66 lines
1.8 KiB
Go
66 lines
1.8 KiB
Go
package hostmode
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// setPXEBootNext points the next boot at a PXE-capable BootOrder
|
|
// entry via efibootmgr --bootnext. Best-effort: absent efibootmgr,
|
|
// non-UEFI firmware, or zero PXE entries all fall through silently —
|
|
// the operator's BIOS/DHCP chain will still PXE-boot on most hosts.
|
|
func setPXEBootNext(ctx context.Context) {
|
|
if _, err := os.Stat("/sys/firmware/efi"); err != nil {
|
|
log.Printf("hostmode: not a UEFI system; skipping efibootmgr")
|
|
return
|
|
}
|
|
bin, err := exec.LookPath("efibootmgr")
|
|
if err != nil {
|
|
log.Printf("hostmode: efibootmgr not installed; skipping")
|
|
return
|
|
}
|
|
boots, err := exec.CommandContext(ctx, bin, "-v").Output()
|
|
if err != nil {
|
|
log.Printf("hostmode: efibootmgr -v: %v", err)
|
|
return
|
|
}
|
|
num := findPXEBootNum(string(boots))
|
|
if num == "" {
|
|
log.Printf("hostmode: no PXE boot entry found")
|
|
return
|
|
}
|
|
if err := exec.CommandContext(ctx, bin, "--bootnext", num).Run(); err != nil {
|
|
log.Printf("hostmode: efibootmgr --bootnext %s: %v", num, err)
|
|
return
|
|
}
|
|
log.Printf("hostmode: efibootmgr --bootnext %s", num)
|
|
}
|
|
|
|
// findPXEBootNum picks the first BootXXXX entry whose description
|
|
// looks like a network boot. efibootmgr -v output lines look like:
|
|
//
|
|
// Boot0003* UEFI: IPv4 Intel I225-V PciRoot(0x0)/Pci(...)/MAC(...)
|
|
// Boot0001* ubuntu HD(1,GPT,...)/File(\EFI\ubuntu\shimx64.efi)
|
|
func findPXEBootNum(out string) string {
|
|
scan := bufio.NewScanner(strings.NewReader(out))
|
|
for scan.Scan() {
|
|
line := scan.Text()
|
|
if !strings.HasPrefix(line, "Boot") || len(line) < 8 {
|
|
continue
|
|
}
|
|
low := strings.ToLower(line)
|
|
if !(strings.Contains(low, "pxe") ||
|
|
strings.Contains(low, "ipv4") ||
|
|
strings.Contains(low, "ipv6") ||
|
|
strings.Contains(low, "network")) {
|
|
continue
|
|
}
|
|
return line[4:8]
|
|
}
|
|
return ""
|
|
}
|