github.com/amanya/packer@v0.12.1-0.20161117214323-902ac5ab2eb6/builder/virtualbox/common/step_shutdown.go (about) 1 package common 2 3 import ( 4 "errors" 5 "fmt" 6 "github.com/mitchellh/multistep" 7 "github.com/mitchellh/packer/packer" 8 "log" 9 "time" 10 ) 11 12 // This step shuts down the machine. It first attempts to do so gracefully, 13 // but ultimately forcefully shuts it down if that fails. 14 // 15 // Uses: 16 // communicator packer.Communicator 17 // driver Driver 18 // ui packer.Ui 19 // vmName string 20 // 21 // Produces: 22 // <nothing> 23 type StepShutdown struct { 24 Command string 25 Timeout time.Duration 26 Delay time.Duration 27 } 28 29 func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction { 30 comm := state.Get("communicator").(packer.Communicator) 31 driver := state.Get("driver").(Driver) 32 ui := state.Get("ui").(packer.Ui) 33 vmName := state.Get("vmName").(string) 34 35 if s.Command != "" { 36 ui.Say("Gracefully halting virtual machine...") 37 log.Printf("Executing shutdown command: %s", s.Command) 38 cmd := &packer.RemoteCmd{Command: s.Command} 39 if err := cmd.StartWithUi(comm, ui); err != nil { 40 err := fmt.Errorf("Failed to send shutdown command: %s", err) 41 state.Put("error", err) 42 ui.Error(err.Error()) 43 return multistep.ActionHalt 44 } 45 46 // Wait for the machine to actually shut down 47 log.Printf("Waiting max %s for shutdown to complete", s.Timeout) 48 shutdownTimer := time.After(s.Timeout) 49 for { 50 running, _ := driver.IsRunning(vmName) 51 if !running { 52 53 if s.Delay.Nanoseconds() > 0 { 54 log.Printf("Delay for %s after shutdown to allow locks to clear...", s.Delay) 55 time.Sleep(s.Delay) 56 } 57 58 break 59 } 60 61 select { 62 case <-shutdownTimer: 63 err := errors.New("Timeout while waiting for machine to shut down.") 64 state.Put("error", err) 65 ui.Error(err.Error()) 66 return multistep.ActionHalt 67 default: 68 time.Sleep(500 * time.Millisecond) 69 } 70 } 71 } else { 72 ui.Say("Halting the virtual machine...") 73 if err := driver.Stop(vmName); err != nil { 74 err := fmt.Errorf("Error stopping VM: %s", err) 75 state.Put("error", err) 76 ui.Error(err.Error()) 77 return multistep.ActionHalt 78 } 79 } 80 81 log.Println("VM shut down.") 82 return multistep.ActionContinue 83 } 84 85 func (s *StepShutdown) Cleanup(state multistep.StateBag) {}