From a44cef6d7bb2ff6f2a2f9951dbafb67a789e604d Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sat, 3 Feb 2018 15:33:37 -0800 Subject: [PATCH] Add an advanced option to pass in a raw iPXE script. The feature is heavily laced with warnings and a complete lack of promises around future compatibility. But within those parameters, it might allow some people to do cool things. Fixes #60. --- pixiecore/README.api.md | 41 +++++++++++++++++++++++++++++++++++++++++ pixiecore/booters.go | 15 +++++++++++---- pixiecore/http.go | 4 ++++ pixiecore/pixiecore.go | 10 ++++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) diff --git a/pixiecore/README.api.md b/pixiecore/README.api.md index bd77e41..d3d537a 100644 --- a/pixiecore/README.api.md +++ b/pixiecore/README.api.md @@ -172,6 +172,47 @@ reasonable starting point nonetheless. It will instruct pixecore to boot Tiny Core Linux' kernel and initrd(s), directly from upstream servers. +## Advanced, non-guaranteed features + +### Custom iPXE boot script + +Pixiecore aims to abstract away the details of the network boot +process. This gives it the freedom to adjust the exact sequence of +events as more firmware bugs and quirks are discovered in the wild, +and simplifies API design because you only have to specify what you +want the _end_ state to be, not manage the intermediate stages. + +However, in some use cases, you may want to do advanced things within +the bootloader, prior to booting the OS. For these cases, the API +supports passing a raw iPXE boot script. + +Please note that **this is not a stable interface**, and never will +be. iPXE is an implementation detail of Pixiecore's boot process, and +may change at some point in the future without warning. Additionally, +new booting methods may be added that don't use iPXE at all (for +example, the new RedFish machine management APIs). + +By using this advanced feature, you understand that this may break in +future versions of Pixiecore. It's up to you to verify that your use +case continues to work as Pixiecore updates. We still welcome bug +reports if you're using this feature, just be aware that some of them +may end up being "won't fix, working as intended." + +Additionally, note that it is _your_ responsibility to successfully +complete the boot process, Pixiecore's involvement ends with serving +your iPXE script. Pixiecore does no sanity checking on your script, it +just hands it verbatim to iPXE. + +If you're okay with this disclaimer, you can use this functionality by +just passing an `ipxe-script` element as the only element of your +response: + +```json +{ + "ipxe-script": "#!ipxe\nyour-ipxe-script-here" +} +``` + ## Deprecated features ### Kernel commandline as an object diff --git a/pixiecore/booters.go b/pixiecore/booters.go index f29bee0..af5be82 100644 --- a/pixiecore/booters.go +++ b/pixiecore/booters.go @@ -171,15 +171,22 @@ func (b *apibooter) BootSpec(m Machine) (*Spec, error) { } r := struct { - Kernel string `json:"kernel"` - Initrd []string `json:"initrd"` - Cmdline interface{} `json:"cmdline"` - Message string `json:"message"` + Kernel string `json:"kernel"` + Initrd []string `json:"initrd"` + Cmdline interface{} `json:"cmdline"` + Message string `json:"message"` + IpxeScript string `json:"ipxe-script"` }{} if err = json.NewDecoder(body).Decode(&r); err != nil { return nil, err } + if r.IpxeScript != "" { + return &Spec{ + IpxeScript: r.IpxeScript, + }, nil + } + r.Kernel, err = b.makeURLAbsolute(r.Kernel) if err != nil { return nil, err diff --git a/pixiecore/http.go b/pixiecore/http.go index 41978ad..cfc0e98 100644 --- a/pixiecore/http.go +++ b/pixiecore/http.go @@ -181,6 +181,10 @@ func (s *Server) handleBooting(w http.ResponseWriter, r *http.Request) { } func ipxeScript(mach Machine, spec *Spec, serverHost string) ([]byte, error) { + if spec.IpxeScript != "" { + return []byte(spec.IpxeScript), nil + } + if spec.Kernel == "" { return nil, errors.New("spec is missing Kernel") } diff --git a/pixiecore/pixiecore.go b/pixiecore/pixiecore.go index e7bb94a..2243f4a 100644 --- a/pixiecore/pixiecore.go +++ b/pixiecore/pixiecore.go @@ -83,6 +83,16 @@ type Spec struct { Cmdline string // Message to print on the client machine before booting. Message string + + // A raw iPXE script to run. Overrides all of the above. + // + // THIS IS NOT A STABLE INTERFACE. This will only work for + // machines that get booted via iPXE. Currently, that is all of + // them, but there is no guarantee that this will remain + // true. When passing a custom iPXE script, it is your + // responsibility to make the boot succeed, Pixiecore's + // involvement ends when it serves your script. + IpxeScript string } func expandCmdline(tpl string, funcs template.FuncMap) (string, error) {