From 636c75745c72c32201901817a1b7738f1d0ffe88 Mon Sep 17 00:00:00 2001 From: Zexi Date: Thu, 16 May 2019 13:37:27 +0800 Subject: [PATCH] baremetal: support http download kernel and initramfs for pxe boot --- pkg/baremetal/manager.go | 37 +++++++++++++++++++++++--------- pkg/baremetal/nic.go | 6 +++++- pkg/baremetal/options/options.go | 3 ++- pkg/baremetal/service/service.go | 17 +++++++++++++++ 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/pkg/baremetal/manager.go b/pkg/baremetal/manager.go index 2cde791ac2..bf5375f7f1 100644 --- a/pkg/baremetal/manager.go +++ b/pkg/baremetal/manager.go @@ -191,7 +191,7 @@ func (m *SBaremetalManager) GetBaremetalById(bmId string) *SBaremetalInstance { } func (m *SBaremetalManager) GetBaremetalByMac(mac net.HardwareAddr) pxe.IBaremetalInstance { - var obj *SBaremetalInstance + var obj pxe.IBaremetalInstance getter := func(key, val interface{}) bool { instance := val.(*SBaremetalInstance) if instance.GetNicByMac(mac) != nil { @@ -690,24 +690,41 @@ func (b *SBaremetalInstance) GetNotifyUrl() string { return fmt.Sprintf("%s/baremetals/%s/notify", b.manager.Agent.GetManagerUri(), b.GetId()) } +func (b *SBaremetalInstance) getTftpFileUrl(filename string) string { + serverIP, err := b.manager.Agent.GetDHCPServerIP() + if err != nil { + log.Errorf("Get http file server: %v", err) + return filename + } + if o.Options.EnableTftpHttpDownload { + return fmt.Sprintf("http://%s:%d/tftp/%s", serverIP, o.Options.Port+1000, filename) + } + return filename +} + func (b *SBaremetalInstance) GetTFTPResponse() string { - resp := `default start + resp := `DEFAULT start serial 1 115200 -label start - menu label ^Start - menu default +LABEL start + MENU LABEL ^Start + MENU default ` if b.NeedPXEBoot() { - resp += " kernel kernel\n" - resp += fmt.Sprintf(" append initrd=initramfs token=%s url=%s", - auth.GetTokenString(), b.GetNotifyUrl()) + resp += fmt.Sprintf(" kernel %s\n", b.getTftpFileUrl("kernel")) + args := []string{ + fmt.Sprintf("initrd=%s", b.getTftpFileUrl("initramfs")), + fmt.Sprintf("token=%s", auth.GetTokenString()), + fmt.Sprintf("url=%s", b.GetNotifyUrl()), + } + resp += fmt.Sprintf(" append %s\n", strings.Join(args, " ")) } else { - resp += " COM32 chain.c32\n" + resp += fmt.Sprintf(" COM32 %s\n", b.getTftpFileUrl("chain.c32")) resp += " APPEND hd0 0\n" + b.ClearSSHConfig() } - log.Infof("%s", resp) + log.Infof("[TFTP response]: \n%s", resp) return resp } diff --git a/pkg/baremetal/nic.go b/pkg/baremetal/nic.go index e0208cc4f7..22be7861aa 100644 --- a/pkg/baremetal/nic.go +++ b/pkg/baremetal/nic.go @@ -76,7 +76,11 @@ func GetNicDHCPConfig( case 6: conf.BootFile = "bootia32.efi" default: - conf.BootFile = "pxelinux.0" + bootFile := "pxelinux.0" + if o.Options.EnableTftpHttpDownload { + bootFile = "lpxelinux.0" + } + conf.BootFile = bootFile } pxePath := filepath.Join(o.Options.TftpRoot, conf.BootFile) if f, err := os.Open(pxePath); err != nil { diff --git a/pkg/baremetal/options/options.go b/pkg/baremetal/options/options.go index df57b0280c..1f4ef81ed1 100644 --- a/pkg/baremetal/options/options.go +++ b/pkg/baremetal/options/options.go @@ -22,7 +22,7 @@ type BaremetalOptions struct { ListenInterface string `help:"Master net interface of baremetal server" default:"br0"` AccessAddress string `help:"Management IP address of baremetal server, only need to use when multiple address bind to ListenInterface"` ListenAddress string `help:"PXE serve IP address to select when multiple address bind to ListenInterface" default:"0.0.0.0"` - TftpRoot string `help:"tftp root directory"` + TftpRoot string `default:"/opt/cloud/yunion/baremetal" help:"tftp root directory"` AutoRegisterBaremetal bool `default:"true" help:"Automatically create a baremetal instance"` BaremetalsPath string `default:"/opt/cloud/workspace/baremetals" help:"Path for baremetals configuration files"` LinuxDefaultRootUser bool `default:"false" help:"Default account for linux system is root"` @@ -41,6 +41,7 @@ type BaremetalOptions struct { DefaultStrongIpmiPassword string `help:"Default strong IPMI passowrd"` WindowsDefaultAdminUser bool `default:"true" help:"Default account for Windows system is Administrator"` + EnableTftpHttpDownload bool `default:"true" help:"Pxelinux download file through http"` } var ( diff --git a/pkg/baremetal/service/service.go b/pkg/baremetal/service/service.go index 0eb73c885b..addc55d8ec 100644 --- a/pkg/baremetal/service/service.go +++ b/pkg/baremetal/service/service.go @@ -15,6 +15,8 @@ package service import ( + "fmt" + "net/http" "os" "yunion.io/x/log" @@ -43,12 +45,27 @@ func (s *BaremetalService) StartService() { app := app_common.InitApp(&o.Options.CommonOptions, false) handler.InitHandlers(app) + s.startFileServer() + app_common.ServeForeverWithCleanup(app, &o.Options.CommonOptions, func() { tasks.OnStop() baremetal.Stop() }) } +func (s *BaremetalService) startFileServer() { + if !o.Options.EnableTftpHttpDownload { + return + } + fs := http.FileServer(http.Dir(o.Options.TftpRoot)) + http.Handle("/tftp/", http.StripPrefix("/tftp/", fs)) + go func() { + if err := http.ListenAndServe(fmt.Sprintf("%s:%d", o.Options.Address, o.Options.Port+1000), nil); err != nil { + panic(fmt.Sprintf("start http file server: %v", err)) + } + }() +} + func (s *BaremetalService) startAgent() { err := baremetal.Start() if err != nil {