diff options
| author | Geert Stappers <stappers@stappers.it> | 2023-01-05 00:21:47 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-01-04 15:21:47 -0800 |
| commit | 1c79728984af1b0b065ce5879581f41fa9f03da3 (patch) | |
| tree | 2a567b5d9542683f450b663d3bef91f218ab35d4 | |
| parent | 046315273f2bdc6b268fc1d05704cbdbd42d29fb (diff) | |
feat: add human-friendly entry point
* Added /start as entry point, for humans and iPXE
The '/poll/1/${netX/mac:hexhyp}' is fairly iPXE internal, not something
that invites curious people to look better at shoelaces. Neither it is
looking nice in DHCP server configuration.
This change adds a HTTP handler for '/start'. And '/start' points
to '/poll/1/${netX/mac:hexhyp}'. The benefit of it is that human visible
documentation can replace the "voodoo" '/poll/1/${netX/mac:hexhyp}'
with "friendly" '/start'.
Because it is an addition are the existing HTTP handlers not effected,
neither the installed deployments effected.
Signed-off-by: Geert Stappers <stappers@stappers.it>
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | docs/shoelaces.8.scd | 4 | ||||
| -rw-r--r-- | internal/handlers/polling.go | 10 | ||||
| -rw-r--r-- | internal/polling/polling.go | 30 | ||||
| -rw-r--r-- | internal/router/router.go | 3 | ||||
| -rw-r--r-- | web/templates/html/index.html | 2 |
6 files changed, 48 insertions, 5 deletions
@@ -141,7 +141,7 @@ with your TFTP and Shoelaces server addresses. # dhcp.conf next-server <your-tftp-server>; if exists user-class and option user-class = "iPXE" { - filename "http://<shoelaces-server>/poll/1/${netX/mac:hexhyp}"; + filename "http://<shoelaces-server>/start"; } else { filename "undionly.kpxe"; } @@ -153,7 +153,7 @@ putting it in `dnsmasq.d/ipxe.conf`: ```txt dhcp-match=set:ipxe,175 # iPXE sends a 175 option. dhcp-boot=tag:!ipxe,undionly.kpxe -dhcp-boot=http://<shoelaces-server>/poll/1/${netX/mac:hexhyp} +dhcp-boot=http://<shoelaces-server>/start ``` The **${netX/mac:hexhyp}** strings represents the MAC address of the booting diff --git a/docs/shoelaces.8.scd b/docs/shoelaces.8.scd index 445994c..f803dd3 100644 --- a/docs/shoelaces.8.scd +++ b/docs/shoelaces.8.scd @@ -88,7 +88,7 @@ debug=true # dhcp.conf next-server <your-tftp-server>; if exists user-class and option user-class = "iPXE" { - filename "http://<shoelaces-server>/poll/1/${netX/mac:hexhyp}"; + filename "http://<shoelaces-server>/start"; } else { filename "undionly.kpxe"; } @@ -100,7 +100,7 @@ the following snippet: ``` dhcp-match=set:ipxe,175 # iPXE sends a 175 option. dhcp-boot=tag:!ipxe,undionly.kpxe -dhcp-boot=http://<shoelaces-server>/poll/1/${netX/mac:hexhyp} +dhcp-boot=http://<shoelaces-server>/start ``` A TFTP server such as *tftpd*(8) must be configured to serve the iPXE executable, diff --git a/internal/handlers/polling.go b/internal/handlers/polling.go index 12f36e2..51fd8ad 100644 --- a/internal/handlers/polling.go +++ b/internal/handlers/polling.go @@ -28,6 +28,16 @@ import ( "github.com/thousandeyes/shoelaces/internal/utils" ) +// StartPollingHandler is called by iPXE boot agents. It returns the poll script. +func StartPollingHandler(w http.ResponseWriter, r *http.Request) { + env := envFromRequest(r) + + script := polling.GenStartScript(env.Logger, env.BaseURL) + + w.Write([]byte(script)) +} + + // PollHandler is called by iPXE boot agents. It returns the boot script // specified on the configuration or, if the host is unknown, it makes it // retry for a while until the user specifies alternative IPXE boot script. diff --git a/internal/polling/polling.go b/internal/polling/polling.go index 853a751..cfd489f 100644 --- a/internal/polling/polling.go +++ b/internal/polling/polling.go @@ -34,6 +34,16 @@ import ( type ManualAction int const ( + startScript = "#!ipxe\n" + + "echo Shoelaces starts polling\n" + + "chain --autofree --replace \\\n" + + " http://{{.baseURL}}/poll/1/${netX/mac:hexhyp}\n" + + "#\n" + + "#\n" + + "# Do\n" + + "# curl http://{{.baseURL}}/poll/1/06-66-de-ad-be-ef\n" + + "# to get an idea about what iPXE will receive.\n" + maxRetry = 10 retryScript = "#!ipxe\n" + @@ -226,6 +236,26 @@ func setHostName(params map[string]interface{}, mac string) { } } +func GenStartScript(logger log.Logger, baseURL string) string { + variablesMap := map[string]interface{}{} + parsedTemplate := &bytes.Buffer{} + + tmpl, err := template.New("retry").Parse(startScript) + if err != nil { + logger.Info("component", "polling", "msg", "Error parsing start template") + panic(err) + } + + variablesMap["baseURL"] = baseURL + err = tmpl.Execute(parsedTemplate, variablesMap) + if err != nil { + logger.Info("component", "polling", "msg", "Error executing start template") + panic(err) + } + + return parsedTemplate.String() +} + func genBootScript(logger log.Logger, templateRenderer *templates.ShoelacesTemplates, baseURL string, script *mappings.Script) string { script.Params["baseURL"] = utils.BaseURLforEnvName(baseURL, script.Environment) text, err := templateRenderer.RenderTemplate(logger, script.Name, script.Params, script.Environment) diff --git a/internal/router/router.go b/internal/router/router.go index d729d16..1313705 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -53,6 +53,9 @@ func ShoelacesRouter(env *environment.Environment) http.Handler { r.PathPrefix("/configs/").Handler(http.StripPrefix("/configs/", handlers.TemplateServer())) + // Starting point for iPXE boot agents, usualy defined by DHCP server. + // Gets the iPXE boot agents into the polling loop. + r.HandleFunc("/start", handlers.StartPollingHandler).Methods("GET") // Called by iPXE boot agents, returns boot script specified on the configuration // or if the host is unknown makes it retry for a while until the user specifies // alternative ipxe boot script diff --git a/web/templates/html/index.html b/web/templates/html/index.html index 4f09ba9..ea93c01 100644 --- a/web/templates/html/index.html +++ b/web/templates/html/index.html @@ -31,7 +31,7 @@ <div class="center-block col-md-6"> <div class="card"> <div class="card-body"> - <p class="text-center">Shoelaces is waiting for a server to boot. Using iPXE, your server should reach the following endpoint: <br /> <b class="text-primary-custom">http://{{ .BaseURL }}/poll/1/<MAC></b> </p> + <p class="text-center">Shoelaces is waiting for a server to boot. Using iPXE, your server should reach the following endpoint: <br /> <b class="text-primary-custom">http://{{ .BaseURL }}/start</b> </p> <p class="text-center">You can automate this process by setting up a DHCP server.</p> </div> </div> |
