From d0fd698fb52242a03971f93112b000d3d63d7fd0 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Tue, 17 May 2016 17:10:10 -0400 Subject: [PATCH 1/2] Pause between boot_commands when debugging a Parallels 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 template. --- builder/parallels/common/step_type_boot_command.go | 13 ++++++++++++- builder/parallels/iso/builder.go | 5 ++++- builder/parallels/pvm/builder.go | 5 ++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/builder/parallels/common/step_type_boot_command.go b/builder/parallels/common/step_type_boot_command.go index 1f3a3ef4c..a1b3d562d 100644 --- a/builder/parallels/common/step_type_boot_command.go +++ b/builder/parallels/common/step_type_boot_command.go @@ -40,10 +40,16 @@ type StepTypeBootCommand struct { } func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction { + debug := state.Get("debug").(bool) httpPort := state.Get("http_port").(uint) ui := state.Get("ui").(packer.Ui) driver := state.Get("driver").(Driver) + var pauseFn multistep.DebugPauseFn + if debug { + pauseFn = state.Get("pauseFn").(multistep.DebugPauseFn) + } + hostIp := "0.0.0.0" if len(s.HostInterfaces) > 0 { @@ -69,7 +75,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) @@ -123,6 +129,11 @@ func (s *StepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction } codes = append(codes, code) } + + if pauseFn != nil { + pauseFn(multistep.DebugLocationAfterRun, fmt.Sprintf("boot_command[%d]: %s", i, command), state) + } + log.Printf("Sending scancodes: %#v", codes) if err := driver.SendKeyScanCodes(s.VMName, codes...); err != nil { err := fmt.Errorf("Error sending boot command: %s", err) diff --git a/builder/parallels/iso/builder.go b/builder/parallels/iso/builder.go index cd59d2211..546ff8890 100644 --- a/builder/parallels/iso/builder.go +++ b/builder/parallels/iso/builder.go @@ -209,15 +209,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/parallels/pvm/builder.go b/builder/parallels/pvm/builder.go index b0b675fb6..b62181b06 100644 --- a/builder/parallels/pvm/builder.go +++ b/builder/parallels/pvm/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("hook", hook) state.Put("ui", ui) @@ -108,9 +109,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 98bae9c98eec1e2fe7049a371b8ef6392b97f260 Mon Sep 17 00:00:00 2001 From: Sean Chittenden Date: Tue, 17 May 2016 17:14:50 -0400 Subject: [PATCH 2/2] Pause between boot_commands when debugging a QEMU build When debugging a build (or maintaining an existing packer template), teach `packer build -debug` how to step through individual `boot_command`s in order to triage the packer template. --- builder/qemu/builder.go | 5 ++++- builder/qemu/step_type_boot_command.go | 12 +++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/builder/qemu/builder.go b/builder/qemu/builder.go index 59490049c..3fc3ff678 100644 --- a/builder/qemu/builder.go +++ b/builder/qemu/builder.go @@ -379,15 +379,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/qemu/step_type_boot_command.go b/builder/qemu/step_type_boot_command.go index 8b599e13f..f720d6f12 100644 --- a/builder/qemu/step_type_boot_command.go +++ b/builder/qemu/step_type_boot_command.go @@ -38,10 +38,16 @@ type stepTypeBootCommand struct{} func (s *stepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) + debug := state.Get("debug").(bool) httpPort := state.Get("http_port").(uint) ui := state.Get("ui").(packer.Ui) 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("127.0.0.1:%d", vncPort)) @@ -72,7 +78,7 @@ func (s *stepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction } ui.Say("Typing the boot command over VNC...") - for _, command := range config.BootCommand { + for i, command := range config.BootCommand { command, err := interpolate.Render(command, &ctx) if err != nil { err := fmt.Errorf("Error preparing boot command: %s", err) @@ -87,6 +93,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) }