From 2431dd9950df1b87ec130f417c292f5557f79203 Mon Sep 17 00:00:00 2001 From: Rolf Neugebauer Date: Tue, 9 Jan 2018 15:35:23 +0000 Subject: [PATCH] cmd/packet: Use IPXEScriptURL instead of passing script via Userdata Using the userdat to pass the iPXE script precludes us from passing actual userdata to the instance. Instead pass a URL to the iPXE script. The script is expected to be a /-packet.ipxe. When starting a server also serve the iPXE script from memory (not the file system). The http server needed extending to differentiate between the serving files and the iPXE script and ServeMux is used to differentiate based on path. A subsequent commit will provide an option to write the iPXE script to disk. Signed-off-by: Rolf Neugebauer --- src/cmd/linuxkit/run_packet.go | 73 ++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/src/cmd/linuxkit/run_packet.go b/src/cmd/linuxkit/run_packet.go index 19dcc2276..144e40c12 100644 --- a/src/cmd/linuxkit/run_packet.go +++ b/src/cmd/linuxkit/run_packet.go @@ -56,7 +56,7 @@ func runPacket(args []string) { fmt.Printf("Options:\n\n") flags.PrintDefaults() } - baseURLFlag := flags.String("base-url", "", "Base URL that the kernel and initrd are served from (or "+packetBaseURL+")") + baseURLFlag := flags.String("base-url", "", "Base URL that the kernel, initrd and iPXE script are served from (or "+packetBaseURL+")") zoneFlag := flags.String("zone", packetDefaultZone, "Packet Zone (or "+packetZoneVar+")") machineFlag := flags.String("machine", packetDefaultMachine, "Packet Machine Type (or "+packetMachineVar+")") apiKeyFlag := flags.String("api-key", "", "Packet API key (or "+packetAPIKeyVar+")") @@ -80,7 +80,7 @@ func runPacket(args []string) { url := getStringValue(packetBaseURL, *baseURLFlag, "") if url == "" { - log.Fatal("Need to specify a value for --base-url where the images are hosted. This URL should contain /%s-kernel and /%s-initrd.img") + log.Fatal("Need to specify a value for --base-url where the images are hosted. This URL should contain /%s-kernel, /%s-initrd.img and /%s-packet.ipxe") } facility := getStringValue(packetZoneVar, *zoneFlag, "") plan := getStringValue(packetMachineVar, *machineFlag, defaultMachine) @@ -101,19 +101,31 @@ func runPacket(args []string) { log.Fatalf("Combination of keep=%t and console=%t makes little sense", *keepFlag, *consoleFlag) } - // Read kernel command line - var cmdline string - if c, err := ioutil.ReadFile(prefix + "-cmdline"); err != nil { - log.Fatalf("Cannot open cmdline file: %v", err) - } else { - cmdline = string(c) - } + ipxeScriptName := fmt.Sprintf("%s-packet.ipxe", name) // Serve files with a local http server var httpServer *http.Server if *serveFlag != "" { + // Read kernel command line + var cmdline string + if c, err := ioutil.ReadFile(prefix + "-cmdline"); err != nil { + log.Fatalf("Cannot open cmdline file: %v", err) + } else { + cmdline = string(c) + } + + ipxeScript := packetIPXEScript(name, url, cmdline, packetMachineToArch(*machineFlag)) + log.Debugf("Using iPXE script:\n%s\n", ipxeScript) + + // Two handlers, one for the iPXE script and one for the kernel/initrd files + mux := http.NewServeMux() + mux.HandleFunc(fmt.Sprintf("/%s", ipxeScriptName), + func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, ipxeScript) + }) fs := serveFiles{[]string{fmt.Sprintf("%s-kernel", name), fmt.Sprintf("%s-initrd.img", name)}} - httpServer = &http.Server{Addr: *serveFlag, Handler: http.FileServer(fs)} + mux.Handle("/", http.FileServer(fs)) + httpServer = &http.Server{Addr: *serveFlag, Handler: mux} go func() { log.Debugf("Listening on http://%s\n", *serveFlag) if err := httpServer.ListenAndServe(); err != nil { @@ -122,16 +134,19 @@ func runPacket(args []string) { }() } - userData := packetIPXEScript(name, url, cmdline, packetMachineToArch(*machineFlag)) - log.Debugf("Using userData of:\n%s\n", userData) - - // Make sure the URL works + // Make sure the URLs work + ipxeURL := fmt.Sprintf("%s/%s", url, ipxeScriptName) initrdURL := fmt.Sprintf("%s/%s-initrd.img", url, name) kernelURL := fmt.Sprintf("%s/%s-kernel", url, name) - log.Infof("Validating URls: %s %s", initrdURL, kernelURL) + log.Infof("Validating URL: %s", ipxeURL) + if err := validateHTTPURL(ipxeURL); err != nil { + log.Fatalf("Invalid iPXE URL %s: %v", ipxeURL, err) + } + log.Infof("Validating URL: %s", kernelURL) if err := validateHTTPURL(kernelURL); err != nil { log.Fatalf("Invalid kernel URL %s: %v", kernelURL, err) } + log.Infof("Validating URL: %s", initrdURL) if err := validateHTTPURL(initrdURL); err != nil { log.Fatalf("Invalid initrd URL %s: %v", initrdURL, err) } @@ -153,11 +168,11 @@ func runPacket(args []string) { log.Debugf("%s\n", string(b)) req := packngo.DeviceUpdateRequest{ - Hostname: hostname, - UserData: userData, - Locked: dev.Locked, - Tags: dev.Tags, - AlwaysPXE: *alwaysPXE, + Hostname: hostname, + Locked: dev.Locked, + Tags: dev.Tags, + IPXEScriptURL: ipxeURL, + AlwaysPXE: *alwaysPXE, } dev, _, err = client.Devices.Update(*deviceFlag, &req) if err != nil { @@ -169,15 +184,15 @@ func runPacket(args []string) { } else { // Create a new device req := packngo.DeviceCreateRequest{ - Hostname: hostname, - Plan: plan, - Facility: facility, - OS: osType, - BillingCycle: billing, - ProjectID: projectID, - UserData: userData, - Tags: tags, - AlwaysPXE: *alwaysPXE, + Hostname: hostname, + Plan: plan, + Facility: facility, + OS: osType, + BillingCycle: billing, + ProjectID: projectID, + Tags: tags, + IPXEScriptURL: ipxeURL, + AlwaysPXE: *alwaysPXE, } dev, _, err = client.Devices.Create(&req) if err != nil {