diff --git a/cmd/boot-script-service/default_api.go b/cmd/boot-script-service/default_api.go index dc779aa..87a11bf 100644 --- a/cmd/boot-script-service/default_api.go +++ b/cmd/boot-script-service/default_api.go @@ -89,6 +89,7 @@ type scriptParams struct { xname string nid string referralToken string + mac string } // Note that we allow an empty string if the env variable is defined as such. @@ -689,6 +690,11 @@ func buildParams(bd BootData, sp scriptParams, role, subRole string) (string, er if sp.referralToken != "" { params = checkParam(params, "bss_referral_token=", sp.referralToken) } + // Add BOOTIF to params to force 1st mac + if sp.mac != "" { + bootif := "01-" + strings.ReplaceAll(sp.mac, ":", "-") + params = checkParam(params, "BOOTIF=", bootif) + } // Inject the cloud init address info into the kernel params. If the target // image does not have cloud-init enabled this wont hurt anything. @@ -841,7 +847,7 @@ func BootscriptGet(w http.ResponseWriter, r *http.Request) { log.Printf("BSS request failed: bootscript request without mac=, name=, or nid= parameter") return } - sp := scriptParams{comp.ID, comp.NID.String(), bd.ReferralToken} + sp := scriptParams{comp.ID, comp.NID.String(), bd.ReferralToken, mac} debugf("bd: %v\n", bd) debugf("comp: %v\n", comp) diff --git a/cmd/boot-script-service/default_api_test.go b/cmd/boot-script-service/default_api_test.go index ba320fe..6d6f40c 100644 --- a/cmd/boot-script-service/default_api_test.go +++ b/cmd/boot-script-service/default_api_test.go @@ -311,6 +311,113 @@ func TestBuildParams_Success(t *testing.T) { "nid=0", fmt.Sprintf("ds=nocloud-net;s=%s/", advertiseAddress), }}, + { + // BOOTIF injection with MAC address + BootData{ + Params: "root=nfs:example/path/to/rootfs:ro", + Kernel: ImageData{Path: "http://example/path/to/vmlinuz"}, + Initrd: ImageData{Path: "http://example/path/to/initramfs.img"}, + }, + scriptParams{ + xname: "x0000c0s0b0n0", + nid: "0", + mac: "aa:bb:cc:dd:ee:ff", + }, + []string{ + "initrd=initrd", + "root=nfs:example/path/to/rootfs:ro", + "xname=x0000c0s0b0n0", + "nid=0", + "BOOTIF=01-aa-bb-cc-dd-ee-ff", + fmt.Sprintf("ds=nocloud-net;s=%s/", advertiseAddress), + }, + }, + { + // No BOOTIF injection when mac is empty + BootData{ + Params: "root=nfs:example/path/to/rootfs:ro", + Kernel: ImageData{Path: "http://example/path/to/vmlinuz"}, + Initrd: ImageData{Path: "http://example/path/to/initramfs.img"}, + }, + scriptParams{ + xname: "x0000c0s0b0n0", + nid: "0", + mac: "", + }, + []string{ + "initrd=initrd", + "root=nfs:example/path/to/rootfs:ro", + "xname=x0000c0s0b0n0", + "nid=0", + fmt.Sprintf("ds=nocloud-net;s=%s/", advertiseAddress), + }, + }, + { + // Existing BOOTIF in params is preserved (not overwritten) + BootData{ + Params: "root=nfs:example/path/to/rootfs:ro BOOTIF=01-11-22-33-44-55-66", + Kernel: ImageData{Path: "http://example/path/to/vmlinuz"}, + Initrd: ImageData{Path: "http://example/path/to/initramfs.img"}, + }, + scriptParams{ + xname: "x0000c0s0b0n0", + nid: "0", + mac: "aa:bb:cc:dd:ee:ff", + }, + []string{ + "initrd=initrd", + "root=nfs:example/path/to/rootfs:ro", + "BOOTIF=01-11-22-33-44-55-66", + "xname=x0000c0s0b0n0", + "nid=0", + fmt.Sprintf("ds=nocloud-net;s=%s/", advertiseAddress), + }, + }, + { + // BOOTIF with uppercase MAC address + BootData{ + Params: "root=nfs:example/path/to/rootfs:ro", + Kernel: ImageData{Path: "http://example/path/to/vmlinuz"}, + Initrd: ImageData{Path: "http://example/path/to/initramfs.img"}, + }, + scriptParams{ + xname: "x0000c0s0b0n0", + nid: "0", + mac: "AA:BB:CC:DD:EE:FF", + }, + []string{ + "initrd=initrd", + "root=nfs:example/path/to/rootfs:ro", + "xname=x0000c0s0b0n0", + "nid=0", + "BOOTIF=01-AA-BB-CC-DD-EE-FF", + fmt.Sprintf("ds=nocloud-net;s=%s/", advertiseAddress), + }, + }, + { + // BOOTIF with all parameters (mac, referralToken, kernel params) + BootData{ + Params: "root=nfs:example/path/to/rootfs:ro", + Kernel: ImageData{Path: "http://example/path/to/vmlinuz", Params: "console=ttyS0"}, + Initrd: ImageData{Path: "http://example/path/to/initramfs.img"}, + }, + scriptParams{ + xname: "x0000c0s0b0n0", + nid: "0", + referralToken: "test_token", + mac: "00:11:22:33:44:55", + }, + []string{ + "initrd=initrd", + "root=nfs:example/path/to/rootfs:ro", + "console=ttyS0", + "xname=x0000c0s0b0n0", + "nid=0", + "bss_referral_token=test_token", + "BOOTIF=01-00-11-22-33-44-55", + fmt.Sprintf("ds=nocloud-net;s=%s/", advertiseAddress), + }, + }, } for _, tc := range test_cases {