From 9b3f8a4be92e920545c3b9f13601bab15c358f32 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Tue, 17 May 2016 03:50:00 -0400 Subject: [PATCH 1/2] Pause between boot_commands when debugging a VMware build When debugging a build (or maintaining an existing packer file), teach `packer build -debug` how to step through individual `boot_command`s in order to triage the packer file. ``` ==> vmware-iso: Typing the boot command over VNC... ==> vmware-iso: Pausing after run of step 'boot_command[0]: '. Press enter to continue. ==> vmware-iso: Pausing after run of step 'boot_command[1]: '. Press enter to continue. ==> vmware-iso: Pausing after run of step 'boot_command[2]: freebsd-vagrant'. Press enter to continue. ==> vmware-iso: Pausing after run of step 'boot_command[3]: '. Press enter to continue. ^C ``` --- builder/vmware/common/step_type_boot_command.go | 12 +++++++++++- builder/vmware/iso/builder.go | 5 ++++- builder/vmware/vmx/builder.go | 5 ++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/builder/vmware/common/step_type_boot_command.go b/builder/vmware/common/step_type_boot_command.go index 3959e5517..9750aaa71 100644 --- a/builder/vmware/common/step_type_boot_command.go +++ b/builder/vmware/common/step_type_boot_command.go @@ -40,12 +40,18 @@ type StepTypeBootCommand struct { } func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction { + debug := state.Get("debug").(bool) driver := state.Get("driver").(Driver) httpPort := state.Get("http_port").(uint) ui := state.Get("ui").(packer.Ui) vncIp := state.Get("vnc_ip").(string) vncPort := state.Get("vnc_port").(uint) + var pauseFn multistep.DebugPauseFn + if debug { + pauseFn = state.Get("pauseFn").(multistep.DebugPauseFn) + } + // Connect to VNC ui.Say("Connecting to VM via VNC") nc, err := net.Dial("tcp", fmt.Sprintf("%s:%d", vncIp, vncPort)) @@ -95,7 +101,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction } ui.Say("Typing the boot command over VNC...") - for _, command := range s.BootCommand { + for i, command := range s.BootCommand { command, err := interpolate.Render(command, &s.Ctx) if err != nil { err := fmt.Errorf("Error preparing boot command: %s", err) @@ -110,6 +116,10 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction return multistep.ActionHalt } + if pauseFn != nil { + pauseFn(multistep.DebugLocationAfterRun, fmt.Sprintf("boot_command[%d]: %s", i, command), state) + } + vncSendString(c, command) } diff --git a/builder/vmware/iso/builder.go b/builder/vmware/iso/builder.go index b70f6b800..d1e5fd1fe 100755 --- a/builder/vmware/iso/builder.go +++ b/builder/vmware/iso/builder.go @@ -208,6 +208,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe state := new(multistep.BasicStateBag) state.Put("cache", cache) state.Put("config", &b.config) + state.Put("debug", b.config.PackerDebug) state.Put("dir", dir) state.Put("driver", driver) state.Put("hook", hook) @@ -304,9 +305,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe // Run! if b.config.PackerDebug { + pauseFn := common.MultistepDebugFn(ui) + state.Put("pauseFn", pauseFn) b.runner = &multistep.DebugRunner{ Steps: steps, - PauseFn: common.MultistepDebugFn(ui), + PauseFn: pauseFn, } } else { b.runner = &multistep.BasicRunner{Steps: steps} diff --git a/builder/vmware/vmx/builder.go b/builder/vmware/vmx/builder.go index 218edfa34..2de9de5f7 100644 --- a/builder/vmware/vmx/builder.go +++ b/builder/vmware/vmx/builder.go @@ -46,6 +46,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe // Set up the state. state := new(multistep.BasicStateBag) state.Put("config", b.config) + state.Put("debug", b.config.PackerDebug) state.Put("dir", dir) state.Put("driver", driver) state.Put("hook", hook) @@ -120,9 +121,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe // Run the steps. if b.config.PackerDebug { + pauseFn := common.MultistepDebugFn(ui) + state.Put("pauseFn", pauseFn) b.runner = &multistep.DebugRunner{ Steps: steps, - PauseFn: common.MultistepDebugFn(ui), + PauseFn: pauseFn, } } else { b.runner = &multistep.BasicRunner{Steps: steps} From 3ca4782b564329b43ec3822b577f3b1bbaf216fc Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Tue, 17 May 2016 04:03:45 -0400 Subject: [PATCH 2/2] Pause between boot_commands when debugging a Virtualbox build When debugging a build (or maintaining an existing packer file), teach `packer build -debug` how to step through individual `boot_command`s in order to triage the packer file. --- builder/virtualbox/common/step_type_boot_command.go | 12 +++++++++++- builder/virtualbox/iso/builder.go | 5 ++++- builder/virtualbox/ovf/builder.go | 5 ++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/builder/virtualbox/common/step_type_boot_command.go b/builder/virtualbox/common/step_type_boot_command.go index 4d0d3cfff..d227cf760 100644 --- a/builder/virtualbox/common/step_type_boot_command.go +++ b/builder/virtualbox/common/step_type_boot_command.go @@ -38,11 +38,17 @@ type StepTypeBootCommand struct { } func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction { + debug := state.Get("debug").(bool) driver := state.Get("driver").(Driver) httpPort := state.Get("http_port").(uint) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) + var pauseFn multistep.DebugPauseFn + if debug { + pauseFn = state.Get("pauseFn").(multistep.DebugPauseFn) + } + s.Ctx.Data = &bootCommandTemplateData{ "10.0.2.2", httpPort, @@ -50,7 +56,7 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction } ui.Say("Typing the boot command...") - for _, command := range s.BootCommand { + for i, command := range s.BootCommand { command, err := interpolate.Render(command, &s.Ctx) if err != nil { err := fmt.Errorf("Error preparing boot command: %s", err) @@ -81,6 +87,10 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction return multistep.ActionHalt } + if pauseFn != nil { + pauseFn(multistep.DebugLocationAfterRun, fmt.Sprintf("boot_command[%d]: %s", i, command), state) + } + if err := driver.VBoxManage("controlvm", vmName, "keyboardputscancode", code); err != nil { err := fmt.Errorf("Error sending boot command: %s", err) state.Put("error", err) diff --git a/builder/virtualbox/iso/builder.go b/builder/virtualbox/iso/builder.go index 19c9fd1fb..e4f9ebb2e 100644 --- a/builder/virtualbox/iso/builder.go +++ b/builder/virtualbox/iso/builder.go @@ -268,15 +268,18 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe state := new(multistep.BasicStateBag) state.Put("cache", cache) state.Put("config", &b.config) + state.Put("debug", b.config.PackerDebug) state.Put("driver", driver) state.Put("hook", hook) state.Put("ui", ui) // Run if b.config.PackerDebug { + pauseFn := common.MultistepDebugFn(ui) + state.Put("pauseFn", pauseFn) b.runner = &multistep.DebugRunner{ Steps: steps, - PauseFn: common.MultistepDebugFn(ui), + PauseFn: pauseFn, } } else { b.runner = &multistep.BasicRunner{Steps: steps} diff --git a/builder/virtualbox/ovf/builder.go b/builder/virtualbox/ovf/builder.go index 70a1122f3..fa9c68c2f 100644 --- a/builder/virtualbox/ovf/builder.go +++ b/builder/virtualbox/ovf/builder.go @@ -42,6 +42,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe // Set up the state. state := new(multistep.BasicStateBag) state.Put("config", b.config) + state.Put("debug", b.config.PackerDebug) state.Put("driver", driver) state.Put("cache", cache) state.Put("hook", hook) @@ -134,9 +135,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe // Run the steps. if b.config.PackerDebug { + pauseFn := common.MultistepDebugFn(ui) + state.Put("pauseFn", pauseFn) b.runner = &multistep.DebugRunner{ Steps: steps, - PauseFn: common.MultistepDebugFn(ui), + PauseFn: pauseFn, } } else { b.runner = &multistep.BasicRunner{Steps: steps}