From 95e0e465cfafbc21778fc76b610aaace12b11c13 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 24 Dec 2013 18:12:43 -0700 Subject: [PATCH] builder/vmware: move StepRun to common --- builder/vmware/{iso => common}/step_run.go | 56 +++++++++------ builder/vmware/common/step_run_test.go | 82 ++++++++++++++++++++++ builder/vmware/iso/builder.go | 6 +- 3 files changed, 121 insertions(+), 23 deletions(-) rename builder/vmware/{iso => common}/step_run.go (54%) create mode 100644 builder/vmware/common/step_run_test.go diff --git a/builder/vmware/iso/step_run.go b/builder/vmware/common/step_run.go similarity index 54% rename from builder/vmware/iso/step_run.go rename to builder/vmware/common/step_run.go index 6cbd6a171..4e996d833 100644 --- a/builder/vmware/iso/step_run.go +++ b/builder/vmware/common/step_run.go @@ -1,9 +1,8 @@ -package iso +package common import ( "fmt" "github.com/mitchellh/multistep" - vmwcommon "github.com/mitchellh/packer/builder/vmware/common" "github.com/mitchellh/packer/packer" "time" ) @@ -11,39 +10,51 @@ import ( // This step runs the created virtual machine. // // Uses: -// config *config // driver Driver // ui packer.Ui // vmx_path string // // Produces: // -type stepRun struct { +type StepRun struct { + BootWait time.Duration + DurationBeforeStop time.Duration + Headless bool + bootTime time.Time vmxPath string } -func (s *stepRun) Run(state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*config) - driver := state.Get("driver").(vmwcommon.Driver) +func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction { + driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) vmxPath := state.Get("vmx_path").(string) - vncIp := state.Get("vnc_ip").(string) - vncPort := state.Get("vnc_port").(uint) // Set the VMX path so that we know we started the machine s.bootTime = time.Now() s.vmxPath = vmxPath ui.Say("Starting virtual machine...") - if config.Headless { - ui.Message(fmt.Sprintf( - "The VM will be run headless, without a GUI. If you want to\n"+ - "view the screen of the VM, connect via VNC without a password to\n"+ - "%s:%d", vncIp, vncPort)) + if s.Headless { + vncIpRaw, vncIpOk := state.GetOk("vnc_ip") + vncPortRaw, vncPortOk := state.GetOk("vnc_port") + + if vncIpOk && vncPortOk { + vncIp := vncIpRaw.(string) + vncPort := vncPortRaw.(uint) + + ui.Message(fmt.Sprintf( + "The VM will be run headless, without a GUI. If you want to\n"+ + "view the screen of the VM, connect via VNC without a password to\n"+ + "%s:%d", vncIp, vncPort)) + } else { + ui.Message("The VM will be run headless, without a GUI, as configured.\n" + + "If the run isn't succeeding as you expect, please enable the GUI\n" + + "to inspect the progress of the build.") + } } - if err := driver.Start(vmxPath, config.Headless); err != nil { + if err := driver.Start(vmxPath, s.Headless); err != nil { err := fmt.Errorf("Error starting VM: %s", err) state.Put("error", err) ui.Error(err.Error()) @@ -51,9 +62,9 @@ func (s *stepRun) Run(state multistep.StateBag) multistep.StepAction { } // Wait the wait amount - if int64(config.bootWait) > 0 { - ui.Say(fmt.Sprintf("Waiting %s for boot...", config.bootWait.String())) - wait := time.After(config.bootWait) + if int64(s.BootWait) > 0 { + ui.Say(fmt.Sprintf("Waiting %s for boot...", s.BootWait.String())) + wait := time.After(s.BootWait) WAITLOOP: for { select { @@ -71,18 +82,19 @@ func (s *stepRun) Run(state multistep.StateBag) multistep.StepAction { return multistep.ActionContinue } -func (s *stepRun) Cleanup(state multistep.StateBag) { - driver := state.Get("driver").(vmwcommon.Driver) +func (s *StepRun) Cleanup(state multistep.StateBag) { + driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) // If we started the machine... stop it. if s.vmxPath != "" { // If we started it less than 5 seconds ago... wait. sinceBootTime := time.Since(s.bootTime) - waitBootTime := 5 * time.Second + waitBootTime := s.DurationBeforeStop if sinceBootTime < waitBootTime { sleepTime := waitBootTime - sinceBootTime - ui.Say(fmt.Sprintf("Waiting %s to give VMware time to clean up...", sleepTime.String())) + ui.Say(fmt.Sprintf( + "Waiting %s to give VMware time to clean up...", sleepTime.String())) time.Sleep(sleepTime) } diff --git a/builder/vmware/common/step_run_test.go b/builder/vmware/common/step_run_test.go new file mode 100644 index 000000000..9888cdf10 --- /dev/null +++ b/builder/vmware/common/step_run_test.go @@ -0,0 +1,82 @@ +package common + +import ( + "testing" + + "github.com/mitchellh/multistep" +) + +func TestStepRun_impl(t *testing.T) { + var _ multistep.Step = new(StepRun) +} + +func TestStepRun(t *testing.T) { + state := testState(t) + step := new(StepRun) + + state.Put("vmx_path", "foo") + + driver := state.Get("driver").(*DriverMock) + + // Test the run + if action := step.Run(state); action != multistep.ActionContinue { + t.Fatalf("bad action: %#v", action) + } + if _, ok := state.GetOk("error"); ok { + t.Fatal("should NOT have error") + } + + // Test the driver + if !driver.StartCalled { + t.Fatal("start should be called") + } + if driver.StartPath != "foo" { + t.Fatalf("bad: %#v", driver.StartPath) + } + if driver.StartHeadless { + t.Fatal("bad") + } + + // Test cleanup + step.Cleanup(state) + if driver.StopCalled { + t.Fatal("stop should not be called if not running") + } +} + +func TestStepRun_cleanupRunning(t *testing.T) { + state := testState(t) + step := new(StepRun) + + state.Put("vmx_path", "foo") + + driver := state.Get("driver").(*DriverMock) + + // Test the run + if action := step.Run(state); action != multistep.ActionContinue { + t.Fatalf("bad action: %#v", action) + } + if _, ok := state.GetOk("error"); ok { + t.Fatal("should NOT have error") + } + + // Test the driver + if !driver.StartCalled { + t.Fatal("start should be called") + } + if driver.StartPath != "foo" { + t.Fatalf("bad: %#v", driver.StartPath) + } + if driver.StartHeadless { + t.Fatal("bad") + } + + // Mark that it is running + driver.IsRunningResult = true + + // Test cleanup + step.Cleanup(state) + if !driver.StopCalled { + t.Fatal("stop should be called") + } +} diff --git a/builder/vmware/iso/builder.go b/builder/vmware/iso/builder.go index 361048c90..da9d71dec 100644 --- a/builder/vmware/iso/builder.go +++ b/builder/vmware/iso/builder.go @@ -396,7 +396,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &stepHTTPServer{}, &stepConfigureVNC{}, &StepRegister{}, - &stepRun{}, + &vmwcommon.StepRun{ + BootWait: b.config.bootWait, + DurationBeforeStop: 5 * time.Second, + Headless: b.config.Headless, + }, &stepTypeBootCommand{}, &common.StepConnectSSH{ SSHAddress: driver.SSHAddress,