From 7cafcf5879de796b0ead408b00254ae313bcbdae Mon Sep 17 00:00:00 2001 From: Sander Jans Date: Wed, 30 May 2018 13:59:44 +0200 Subject: [PATCH 1/3] Support for local HTTP server --- iso/builder.go | 5 +++++ iso/config.go | 2 ++ iso/step_create.go | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/iso/builder.go b/iso/builder.go index fb2b424bb..c42acd0d4 100644 --- a/iso/builder.go +++ b/iso/builder.go @@ -63,6 +63,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Datastore: b.config.Datastore, Host: b.config.Host, }, + &packerCommon.StepHTTPServer{ + HTTPDir: b.config.HTTPDir, + HTTPPortMin: b.config.HTTPPortMin, + HTTPPortMax: b.config.HTTPPortMax, + }, &common.StepRun{ Config: &b.config.RunConfig, SetOrder: true, diff --git a/iso/config.go b/iso/config.go index f4b486fab..21daf494e 100644 --- a/iso/config.go +++ b/iso/config.go @@ -11,6 +11,7 @@ import ( type Config struct { packerCommon.PackerConfig `mapstructure:",squash"` + packerCommon.HTTPConfig `mapstructure:",squash"` common.ConnectConfig `mapstructure:",squash"` CreateConfig `mapstructure:",squash"` @@ -46,6 +47,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { errs = packer.MultiErrorAppend(errs, c.CreateConfig.Prepare()...) errs = packer.MultiErrorAppend(errs, c.LocationConfig.Prepare()...) errs = packer.MultiErrorAppend(errs, c.HardwareConfig.Prepare()...) + errs = packer.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.CDRomConfig.Prepare()...) errs = packer.MultiErrorAppend(errs, c.BootConfig.Prepare()...) diff --git a/iso/step_create.go b/iso/step_create.go index 122e542e8..30237ee96 100644 --- a/iso/step_create.go +++ b/iso/step_create.go @@ -3,10 +3,13 @@ package iso import ( "context" "fmt" + packerCommon "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" "github.com/jetbrains-infra/packer-builder-vsphere/common" "github.com/jetbrains-infra/packer-builder-vsphere/driver" + "net" + "os" ) type CreateConfig struct { @@ -23,6 +26,29 @@ type CreateConfig struct { USBController bool `mapstructure:"usb_controller"` Notes string `mapstructure:"notes"` + + HTTPIP string `mapstructure:"http_ip"` +} + +func getHostIP(s string) string { + if net.ParseIP(s) != nil { + return s + } + + var ipaddr string + addrs, err := net.InterfaceAddrs() + if err != nil { + fmt.Println(err) + os.Exit(2) + } + + for _, a := range addrs { + if ip, ok := a.(*net.IPNet); ok && !ip.IP.IsLoopback() { + ipaddr = ip.IP.String() + break + } + } + return ipaddr } func (c *CreateConfig) Prepare() []error { @@ -66,6 +92,8 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste } } + packerCommon.SetHTTPIP(getHostIP(s.Config.HTTPIP)) + ui.Say("Creating VM...") vm, err := d.CreateVM(&driver.CreateConfig{ DiskThinProvisioned: s.Config.DiskThinProvisioned, From 1474a0b82d421dda287f2f14a1c384c954048fcb Mon Sep 17 00:00:00 2001 From: Michael Kuzmin Date: Sun, 23 Dec 2018 02:13:31 +0300 Subject: [PATCH 2/3] Interpolate variables in 'boot_command' --- iso/builder.go | 2 ++ iso/config.go | 5 ++++ iso/step_boot_command.go | 58 ++++++++++++++++++++++++++++++++++++---- iso/step_create.go | 28 ------------------- 4 files changed, 60 insertions(+), 33 deletions(-) diff --git a/iso/builder.go b/iso/builder.go index c42acd0d4..cb21ef77d 100644 --- a/iso/builder.go +++ b/iso/builder.go @@ -74,6 +74,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe }, &StepBootCommand{ Config: &b.config.BootConfig, + Ctx: b.config.ctx, + VMName: b.config.VMName, }, &common.StepWaitForIp{}, &communicator.StepConnect{ diff --git a/iso/config.go b/iso/config.go index 21daf494e..4f88fafce 100644 --- a/iso/config.go +++ b/iso/config.go @@ -37,6 +37,11 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { err := config.Decode(c, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &c.ctx, + InterpolateFilter: &interpolate.RenderFilter{ + Exclude: []string{ + "boot_command", + }, + }, }, raws...) if err != nil { return nil, nil, err diff --git a/iso/step_boot_command.go b/iso/step_boot_command.go index 895df03a1..0edec8c53 100644 --- a/iso/step_boot_command.go +++ b/iso/step_boot_command.go @@ -3,12 +3,14 @@ package iso import ( "context" "fmt" - "github.com/hashicorp/packer/common" + packerCommon "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" + "github.com/hashicorp/packer/template/interpolate" "github.com/jetbrains-infra/packer-builder-vsphere/driver" "golang.org/x/mobile/event/key" "log" + "net" "os" "strings" "time" @@ -18,10 +20,17 @@ import ( type BootConfig struct { BootCommand []string `mapstructure:"boot_command"` RawBootWait string `mapstructure:"boot_wait"` // example: "1m30s"; default: "10s" + HTTPIP string `mapstructure:"http_ip"` bootWait time.Duration } +type bootCommandTemplateData struct { + HTTPIP string + HTTPPort uint + Name string +} + func (c *BootConfig) Prepare() []error { var errs []error @@ -40,6 +49,8 @@ func (c *BootConfig) Prepare() []error { type StepBootCommand struct { Config *BootConfig + VMName string + Ctx interpolate.Context } var special = map[string]key.Code{ @@ -71,10 +82,10 @@ var special = map[string]key.Code{ "": key.CodeDownArrow, } -var keyInterval = common.PackerKeyDefault +var keyInterval = packerCommon.PackerKeyDefault func init() { - if delay, err := time.ParseDuration(os.Getenv(common.PackerKeyEnv)); err == nil { + if delay, err := time.ParseDuration(os.Getenv(packerCommon.PackerKeyEnv)); err == nil { keyInterval = delay } } @@ -101,13 +112,29 @@ WAITLOOP: } } - ui.Say("Typing boot command...") + ip := getHostIP(s.Config.HTTPIP) + err := packerCommon.SetHTTPIP(ip) + if err != nil { + state.Put("error", err) + return multistep.ActionHalt + } + s.Ctx.Data = &bootCommandTemplateData{ + ip, + state.Get("http_port").(uint), + s.VMName, + } + ui.Say("Typing boot command...") var keyAlt bool var keyCtrl bool var keyShift bool + for _, command := range s.Config.BootCommand { + message, err := interpolate.Render(command, &s.Ctx) + if err != nil { + state.Put("error", err) + return multistep.ActionHalt + } - for _, message := range s.Config.BootCommand { for len(message) > 0 { if _, ok := state.GetOk(multistep.StateCancelled); ok { return multistep.ActionHalt @@ -205,3 +232,24 @@ WAITLOOP: } func (s *StepBootCommand) Cleanup(state multistep.StateBag) {} + +func getHostIP(s string) string { + if net.ParseIP(s) != nil { + return s + } + + var ipaddr string + addrs, err := net.InterfaceAddrs() + if err != nil { + fmt.Println(err) + os.Exit(2) + } + + for _, a := range addrs { + if ip, ok := a.(*net.IPNet); ok && !ip.IP.IsLoopback() { + ipaddr = ip.IP.String() + break + } + } + return ipaddr +} diff --git a/iso/step_create.go b/iso/step_create.go index 30237ee96..122e542e8 100644 --- a/iso/step_create.go +++ b/iso/step_create.go @@ -3,13 +3,10 @@ package iso import ( "context" "fmt" - packerCommon "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" "github.com/jetbrains-infra/packer-builder-vsphere/common" "github.com/jetbrains-infra/packer-builder-vsphere/driver" - "net" - "os" ) type CreateConfig struct { @@ -26,29 +23,6 @@ type CreateConfig struct { USBController bool `mapstructure:"usb_controller"` Notes string `mapstructure:"notes"` - - HTTPIP string `mapstructure:"http_ip"` -} - -func getHostIP(s string) string { - if net.ParseIP(s) != nil { - return s - } - - var ipaddr string - addrs, err := net.InterfaceAddrs() - if err != nil { - fmt.Println(err) - os.Exit(2) - } - - for _, a := range addrs { - if ip, ok := a.(*net.IPNet); ok && !ip.IP.IsLoopback() { - ipaddr = ip.IP.String() - break - } - } - return ipaddr } func (c *CreateConfig) Prepare() []error { @@ -92,8 +66,6 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste } } - packerCommon.SetHTTPIP(getHostIP(s.Config.HTTPIP)) - ui.Say("Creating VM...") vm, err := d.CreateVM(&driver.CreateConfig{ DiskThinProvisioned: s.Config.DiskThinProvisioned, From d603d9548cb54c2509bb20d5a48a1057364dd52e Mon Sep 17 00:00:00 2001 From: Michael Kuzmin Date: Sun, 23 Dec 2018 03:00:30 +0300 Subject: [PATCH 3/3] Fix IP resolution --- iso/step_boot_command.go | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/iso/step_boot_command.go b/iso/step_boot_command.go index 0edec8c53..3b7845f27 100644 --- a/iso/step_boot_command.go +++ b/iso/step_boot_command.go @@ -112,17 +112,23 @@ WAITLOOP: } } - ip := getHostIP(s.Config.HTTPIP) - err := packerCommon.SetHTTPIP(ip) + ip, err := getHostIP(s.Config.HTTPIP) if err != nil { state.Put("error", err) return multistep.ActionHalt } + err = packerCommon.SetHTTPIP(ip) + if err != nil { + state.Put("error", err) + return multistep.ActionHalt + } + port := state.Get("http_port").(uint) s.Ctx.Data = &bootCommandTemplateData{ ip, - state.Get("http_port").(uint), + port, s.VMName, } + ui.Say(fmt.Sprintf("HTTP server is working at http://%v:%v/", ip, port)) ui.Say("Typing boot command...") var keyAlt bool @@ -233,23 +239,27 @@ WAITLOOP: func (s *StepBootCommand) Cleanup(state multistep.StateBag) {} -func getHostIP(s string) string { - if net.ParseIP(s) != nil { - return s +func getHostIP(s string) (string, error) { + if s != "" { + if net.ParseIP(s) != nil { + return s, nil + } else { + return "", fmt.Errorf("invalid IP address") + } } - var ipaddr string addrs, err := net.InterfaceAddrs() if err != nil { - fmt.Println(err) - os.Exit(2) + return "", err } for _, a := range addrs { - if ip, ok := a.(*net.IPNet); ok && !ip.IP.IsLoopback() { - ipaddr = ip.IP.String() - break + ipnet, ok := a.(*net.IPNet) + if ok && !ipnet.IP.IsLoopback() { + if ipnet.IP.To4() != nil { + return ipnet.IP.String(), nil + } } } - return ipaddr + return "", fmt.Errorf("IP not found") }