Skip to content

Commit

Permalink
Revert "add support for UEFI HTTP Boot"
Browse files Browse the repository at this point in the history
This reverts commit ceb470a.

Something in tinkerbell#216 broke our c2.large.arm provisions. Reverting
this to unblock things that came after while I look into debugging.

Some more info in [tinkerbell#225].

[tinkerbell#225]: tinkerbell#225

Signed-off-by: Manuel Mendez <mmendez@equinix.com>
  • Loading branch information
mmlb committed Dec 1, 2021
1 parent 0728d55 commit 8a893a6
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 105 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
/cmd/boots/boots
/cmd/boots/boots-*-*
coverage.txt
ipxe/ipxe/*.efi
ipxe/ipxe/*.kpxe
tftp/ipxe/
!deploy/stack/.env
.vagrant
deploy/stack/state/webroot/misc/osie/current/*
Expand Down
5 changes: 1 addition & 4 deletions cmd/boots/tftp.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,7 @@ func (t tftpHandler) ReadFile(c tftp.Conn, filename string) (tftp.ReadCloser, er
defer metrics.JobsInProgress.With(labels).Dec()

ip := tftpClientIP(c.RemoteAddr())
filename = path.Clean(filename)
if path.IsAbs(filename) {
filename = filename[1:]
}
filename = path.Base(filename)
l := mainlog.With("client", ip.String(), "event", "open", "filename", filename)

// clients can send traceparent over TFTP by appending the traceparent string
Expand Down
48 changes: 16 additions & 32 deletions dhcp/pxe.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,19 @@ import (

dhcp4 "github.com/packethost/dhcp4-go"
"github.com/pkg/errors"
"github.com/tinkerbell/boots/ipxe"
"go.opentelemetry.io/otel/trace"
)

// from https://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml
var procArchTypes = []string{
"x86 BIOS", // #0 x86_64
"x86 BIOS",
"NEC/PC98 (DEPRECATED)",
"Itanium",
"DEC Alpha (DEPRECATED)",
"Arc x86 (DEPRECATED)",
"Intel Lean Client (DEPRECATED)",
"x86 UEFI",
"x64 UEFI", // #7 x86_64
"x64 UEFI",
"EFI Xscale (DEPRECATED)",
"EBC",
"ARM 32-bit UEFI",
Expand All @@ -29,10 +28,10 @@ var procArchTypes = []string{
"PowerPC ePAPR",
"POWER OPAL v3",
"x86 uefi boot from http",
"x64 uefi boot from http", // #16 x86_64
"x64 uefi boot from http",
"ebc boot from http",
"arm uefi 32 boot from http",
"arm uefi 64 boot from http", // #19 aarch64
"arm uefi 64 boot from http",
"pc/at bios boot from http",
"arm 32 uboot",
"arm 64 uboot",
Expand Down Expand Up @@ -60,9 +59,9 @@ func ProcessorArchType(req *dhcp4.Packet) string {
func Arch(req *dhcp4.Packet) string {
arch := ProcessorArchType(req)
switch arch {
case "x86 BIOS", "x64 UEFI", "x64 uefi boot from http":
case "x86 BIOS", "x64 UEFI":
return "x86_64"
case "ARM 64-bit UEFI", "arm uefi 64 boot from http":
case "ARM 64-bit UEFI":
return "aarch64"
default:
return arch
Expand All @@ -84,24 +83,14 @@ func IsPXE(req *dhcp4.Packet) bool {
}
class, ok := req.GetString(dhcp4.OptionClassID)

return ok && (strings.HasPrefix(class, "PXEClient") || strings.HasPrefix(class, "HTTPClient"))
}

func IsHTTPClient(req *dhcp4.Packet) bool {
if ipxe.IsIPXE(req) {
return true
}

classID, ok := req.GetString(dhcp4.OptionClassID)

return ok && strings.HasPrefix(classID, "HTTPClient")
return ok && strings.HasPrefix(class, "PXEClient")
}

func SetupPXE(ctx context.Context, rep, req *dhcp4.Packet) bool {
if !IsPXE(req) {
return false // not a PXE client
}
if !copyGUID(rep, req) {
if class, ok := req.GetString(dhcp4.OptionClassID); !ok || !strings.HasPrefix(class, "PXEClient") {
return false // not a PXE client
}
dhcplog.With("mac", req.GetCHAddr(), "xid", req.GetXID()).Info("no client GUID provided")
}

Expand Down Expand Up @@ -134,23 +123,18 @@ func SetupPXE(ctx context.Context, rep, req *dhcp4.Packet) bool {
return true
}

func SetFilename(rep *dhcp4.Packet, filename string, nextServer net.IP, httpServerFQDN string, httpClient bool) {
rep.SetSIAddr(nextServer) // next-server: IP address of the TFTP Server.

if httpClient {
filename = "http://" + httpServerFQDN + "/" + filename
rep.SetString(dhcp4.OptionClassID, "HTTPClient")
} else {
rep.SetString(dhcp4.OptionClassID, "PXEClient")
}

func SetFilename(rep *dhcp4.Packet, filename string, nextServer net.IP, pxeClient bool) {
file := rep.File()
if len(filename) > len(file) {
err := errors.New("filename too long, would be truncated")
// req CHaddr and XID == req's
dhcplog.With("mac", rep.GetCHAddr(), "xid", rep.GetXID(), "filename", filename).Fatal(err)
}
copy(file, filename) // filename: Executable (or iPXE script) to boot from.
if pxeClient {
rep.SetString(dhcp4.OptionClassID, "PXEClient")
}
rep.SetSIAddr(nextServer) // next-server: IP address of the TFTP/HTTP Server.
copy(file, filename) // filename: Executable (or iPXE script) to boot from.
}

func copyGUID(rep, req *dhcp4.Packet) bool {
Expand Down
1 change: 0 additions & 1 deletion ipxe/dhcp_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ func IsPacketIPXE(req *dhcp4.Packet) bool {
// TODO: make this actually check for iPXE and use ipxe' build system's ability to set name.
// This way we could set to something like "Packet iPXE" and then just look for that in the identifier sent in dhcp.
// This also means we won't lose ipxe's version number for logging and such.
// see https://ipxe.org/appnote/userclass
if om := GetEncapsulatedOptions(req); om != nil {
if ov, ok := om.GetOption(OptionVersion); ok {
return ok && bytes.Equal(ov, packetVersion)
Expand Down
9 changes: 0 additions & 9 deletions ipxe/files.go

This file was deleted.

20 changes: 11 additions & 9 deletions job/dhcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (j Job) configureDHCP(ctx context.Context, rep, req *dhcp4.Packet) bool {
ipxe.Setup(rep)
}

j.setPXEFilename(rep, isPacket, isARM, isUEFI, dhcp.IsHTTPClient(req))
j.setPXEFilename(rep, isPacket, isARM, isUEFI)
} else {
span.AddEvent("did not SetupPXE because packet is not a PXE request")
}
Expand All @@ -113,7 +113,7 @@ func (j Job) areWeProvisioner() bool {
return j.hardware.HardwareProvisioner() == j.ProvisionerEngineName()
}

func (j Job) setPXEFilename(rep *dhcp4.Packet, isPacket, isARM, isUEFI, isHTTPClient bool) {
func (j Job) setPXEFilename(rep *dhcp4.Packet, isPacket, isARM, isUEFI bool) {
if j.HardwareState() == "in_use" {
if j.InstanceID() == "" {
j.Error(errors.New("setPXEFilename called on a job with no instance"))
Expand All @@ -139,15 +139,16 @@ func (j Job) setPXEFilename(rep *dhcp4.Packet, isPacket, isARM, isUEFI, isHTTPCl
}

var filename string
var pxeClient bool
if !isPacket {
if j.PArch() == "hua" || j.PArch() == "2a2" {
filename = "ipxe/snp-hua.efi"
filename = "snp-hua.efi"
} else if isARM {
filename = "ipxe/snp-nolacp.efi"
filename = "snp-nolacp.efi"
} else if isUEFI {
filename = "ipxe/ipxe.efi"
filename = "ipxe.efi"
} else {
filename = "ipxe/undionly.kpxe"
filename = "undionly.kpxe"
}
} else if !j.isPXEAllowed() {
// Always honor allow_pxe.
Expand All @@ -161,10 +162,11 @@ func (j Job) setPXEFilename(rep *dhcp4.Packet, isPacket, isARM, isUEFI, isHTTPCl

os := j.OperatingSystem()
j.With("instance.state", j.instance.State, "os_slug", os.Slug, "os_distro", os.Distro, "os_version", os.Version).Info()
pxeClient = true
filename = "/nonexistent"
} else {
isHTTPClient = true
filename = "auto.ipxe"
pxeClient = true
filename = "http://" + conf.PublicFQDN + "/auto.ipxe"
}

if filename == "" {
Expand All @@ -174,5 +176,5 @@ func (j Job) setPXEFilename(rep *dhcp4.Packet, isPacket, isARM, isUEFI, isHTTPCl
return
}

dhcp.SetFilename(rep, filename, conf.PublicIPv4, conf.PublicFQDN, isHTTPClient)
dhcp.SetFilename(rep, filename, conf.PublicIPv4, pxeClient)
}
42 changes: 19 additions & 23 deletions job/dhcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,17 @@ func TestSetPXEFilename(t *testing.T) {
conf.PublicFQDN = "boots-testing.packet.net"

var setPXEFilenameTests = []struct {
name string
hState string
id string
iState string
slug string
plan string
allowPXE bool
httpClient bool
packet bool
arm bool
uefi bool
filename string
name string
hState string
id string
iState string
slug string
plan string
allowPXE bool
packet bool
arm bool
uefi bool
filename string
}{
{name: "just in_use",
hState: "in_use"},
Expand All @@ -40,23 +39,20 @@ func TestSetPXEFilename(t *testing.T) {
hState: "in_use", id: "$instance_id", iState: "active", slug: "not_custom_ipxe"},
{name: "active custom ipxe",
hState: "in_use", id: "$instance_id", iState: "active", slug: "custom_ipxe",
filename: "ipxe/undionly.kpxe"},
filename: "undionly.kpxe"},
{name: "active custom ipxe with allow pxe",
hState: "in_use", id: "$instance_id", iState: "active", allowPXE: true,
filename: "ipxe/undionly.kpxe"},
filename: "undionly.kpxe"},
{name: "hua",
plan: "hua", filename: "ipxe/snp-hua.efi"},
plan: "hua", filename: "snp-hua.efi"},
{name: "2a2",
plan: "2a2", filename: "ipxe/snp-hua.efi"},
plan: "2a2", filename: "snp-hua.efi"},
{name: "arm",
arm: true, filename: "ipxe/snp-nolacp.efi"},
arm: true, filename: "snp-nolacp.efi"},
{name: "x86 uefi",
uefi: true, filename: "ipxe/ipxe.efi"},
{name: "x86 uefi http client",
uefi: true, allowPXE: true, httpClient: true,
filename: "http://" + conf.PublicFQDN + "/ipxe/ipxe.efi"},
uefi: true, filename: "ipxe.efi"},
{name: "all defaults",
filename: "ipxe/undionly.kpxe"},
filename: "undionly.kpxe"},
{name: "packet iPXE",
packet: true, filename: "/nonexistent"},
{name: "packet iPXE PXE allowed",
Expand Down Expand Up @@ -91,7 +87,7 @@ func TestSetPXEFilename(t *testing.T) {
instance: instance,
}
rep := dhcp4.NewPacket(42)
j.setPXEFilename(&rep, tt.packet, tt.arm, tt.uefi, tt.httpClient)
j.setPXEFilename(&rep, tt.packet, tt.arm, tt.uefi)
filename := string(bytes.TrimRight(rep.File(), "\x00"))

if tt.filename != filename {
Expand Down
6 changes: 2 additions & 4 deletions job/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ func (j Job) ServeFile(w http.ResponseWriter, req *http.Request, i Installers) {
return
}

// serve iPXE to HTTP clients.
// NB this must handle HEAD/GET and return Content-Length for odd clients
// like the Seeed Studio Odyssey X86J4105 board.
ipxeFilesHandler.ServeHTTP(w, req)
w.WriteHeader(http.StatusNotFound)
j.With("file", base).Info("file not found")
}

func (j Job) ServePhoneHomeEndpoint(w http.ResponseWriter, req *http.Request) {
Expand Down
10 changes: 0 additions & 10 deletions job/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,23 @@ package job
import (
"context"
"net"
"net/http"
"os"
"time"

"github.com/packethost/pkg/log"
"github.com/pkg/errors"
"github.com/tinkerbell/boots/conf"
"github.com/tinkerbell/boots/dhcp"
"github.com/tinkerbell/boots/ipxe"
"github.com/tinkerbell/boots/packet"
tw "github.com/tinkerbell/tink/protos/workflow"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
)

var joblog log.Logger
var ipxeFilesHandler http.Handler
var client packet.Client
var provisionerEngineName string

func Init(l log.Logger) {
joblog = l.Package("http")
ipxeFilesHandler = http.FileServer(http.FS(ipxe.Files))
initRSA()
}

// SetClient sets the client used to interact with the api.
func SetClient(c packet.Client) {
client = c
Expand Down
9 changes: 9 additions & 0 deletions job/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,17 @@ package job

import (
"context"

"github.com/packethost/pkg/log"
)

var joblog log.Logger

func Init(l log.Logger) {
joblog = l.Package("http")
initRSA()
}

func (j Job) Fatal(err error, args ...interface{}) {
j.Logger.AddCallerSkip(1).Error(err, args...)
panic(err)
Expand Down
16 changes: 8 additions & 8 deletions rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ generated_go_files := \
.PHONY: $(generated_go_files)

# build all the ipxe binaries
generated_ipxe_files := ipxe/ipxe/ipxe.efi ipxe/ipxe/snp-hua.efi ipxe/ipxe/snp-nolacp.efi ipxe/ipxe/undionly.kpxe ipxe/ipxe/snp-hua.efi
generated_ipxe_files := tftp/ipxe/ipxe.efi tftp/ipxe/snp-hua.efi tftp/ipxe/snp-nolacp.efi tftp/ipxe/undionly.kpxe tftp/ipxe/snp-hua.efi

# go generate
go_generate:
Expand All @@ -71,15 +71,15 @@ include ipxev.mk
ipxeconfigs := $(wildcard ipxe/ipxe/*.h)

# copy ipxe binaries into location available for go embed
ipxe/ipxe/ipxe.efi: ipxe/ipxe/build/bin-x86_64-efi/ipxe.efi
ipxe/ipxe/snp-nolacp.efi: ipxe/ipxe/build/bin-arm64-efi/snp.efi
ipxe/ipxe/undionly.kpxe: ipxe/ipxe/build/bin/undionly.kpxe
ipxe/ipxe/ipxe.efi ipxe/ipxe/snp-nolacp.efi ipxe/ipxe/undionly.kpxe:
mkdir -p ipxe/ipxe
tftp/ipxe/ipxe.efi: ipxe/ipxe/build/bin-x86_64-efi/ipxe.efi
tftp/ipxe/snp-nolacp.efi: ipxe/ipxe/build/bin-arm64-efi/snp.efi
tftp/ipxe/undionly.kpxe: ipxe/ipxe/build/bin/undionly.kpxe
tftp/ipxe/ipxe.efi tftp/ipxe/snp-nolacp.efi tftp/ipxe/undionly.kpxe:
mkdir -p tftp/ipxe
cp $^ $@

ipxe/ipxe/snp-hua.efi:
mkdir -p ipxe/ipxe
tftp/ipxe/snp-hua.efi:
mkdir -p tftp/ipxe
# we dont build the snp-hua.efi binary. It's checked into git, so here we just copy it over
cp ipxe/bin/snp-hua.efi $@

Expand Down
Loading

0 comments on commit 8a893a6

Please sign in to comment.