From ee4665c12c21f5f6ba4aeffa70cb547109efcb75 Mon Sep 17 00:00:00 2001 From: Michael Kuzmin Date: Sun, 2 Jul 2017 15:27:52 +0300 Subject: [PATCH] shutdown step uses vSphere driver --- driver.go | 35 +++++++++++++++++++++++++++++++---- step_shutdown.go | 41 ++++++++++------------------------------- 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/driver.go b/driver.go index 464372fc2..8b03d3258 100644 --- a/driver.go +++ b/driver.go @@ -10,6 +10,7 @@ import ( "github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/mo" "errors" + "time" ) type Driver struct { @@ -184,14 +185,40 @@ func (d *Driver) powerOff(vm *object.VirtualMachine) error { return err } - if state != types.VirtualMachinePowerStatePoweredOff { - task, err := vm.PowerOff(d.ctx) + if state == types.VirtualMachinePowerStatePoweredOff { + return nil + } + + task, err := vm.PowerOff(d.ctx) + if err != nil { + return err + } + _, err = task.WaitForResult(d.ctx, nil) + return err +} + +func (d *Driver) StartShutdown(vm *object.VirtualMachine) error { + err := vm.ShutdownGuest(d.ctx) + return err +} + +func (d *Driver) WaitForShutdown(vm *object.VirtualMachine, timeout time.Duration) error { + shutdownTimer := time.After(timeout) + for { + powerState, err := vm.PowerState(d.ctx) if err != nil { return err } - _, err = task.WaitForResult(d.ctx, nil) - if err != nil { + if powerState == "poweredOff" { + break + } + + select { + case <-shutdownTimer: + err := errors.New("Timeout while waiting for machine to shut down.") return err + default: + time.Sleep(1 * time.Second) } } return nil diff --git a/step_shutdown.go b/step_shutdown.go index 82e10b415..3de3d4d36 100644 --- a/step_shutdown.go +++ b/step_shutdown.go @@ -8,7 +8,6 @@ import ( "log" "time" "bytes" - "errors" ) type ShutdownConfig struct { @@ -39,17 +38,14 @@ type StepShutdown struct { } func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction { - // is set during the communicator.StepConnect - comm := state.Get("communicator").(packer.Communicator) ui := state.Get("ui").(packer.Ui) - vm := state.Get("vm").(*object.VirtualMachine) + comm := state.Get("communicator").(packer.Communicator) d := state.Get("driver").(Driver) - - ui.Say("Shut down VM...") + vm := state.Get("vm").(*object.VirtualMachine) if s.config.Command != "" { - ui.Say("Gracefully halting virtual machine...") - log.Printf("Executing shutdown command: %s", s.config.Command) + ui.Say("Executing shutdown command...") + log.Printf("Shutdown command: %s", s.config.Command) var stdout, stderr bytes.Buffer cmd := &packer.RemoteCmd{ @@ -62,37 +58,20 @@ func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction { return multistep.ActionHalt } } else { - ui.Say("Forcibly halting virtual machine...") + ui.Say("Shut down VM...") - err := vm.ShutdownGuest(d.ctx) + err := d.StartShutdown(vm) if err != nil { state.Put("error", fmt.Errorf("Cannot shut down VM: %v", err)) return multistep.ActionHalt } } - // Wait for the machine to actually shut down log.Printf("Waiting max %s for shutdown to complete", s.config.Timeout) - shutdownTimer := time.After(s.config.Timeout) - for { - powerState, err := vm.PowerState(d.ctx) - if err != nil { - state.Put("error", err) - return multistep.ActionHalt - } - if powerState == "poweredOff" { - break - } - - select { - case <-shutdownTimer: - err := errors.New("Timeout while waiting for machine to shut down.") - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - default: - time.Sleep(150 * time.Millisecond) - } + err := d.WaitForShutdown(vm, s.config.Timeout) + if err != nil { + state.Put("error", err) + return multistep.ActionHalt } ui.Say("VM stopped")