builder/vmware: move StepRun to common

This commit is contained in:
Mitchell Hashimoto 2013-12-24 18:12:43 -07:00
parent 7f86fa5fef
commit 95e0e465cf
3 changed files with 121 additions and 23 deletions

View File

@ -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:
// <nothing>
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)
}

View File

@ -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")
}
}

View File

@ -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,