github.com/rothwerx/packer@v0.9.0/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 } 27 28 func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction { 29 comm := state.Get("communicator").(packer.Communicator) 30 driver := state.Get("driver").(Driver) 31 ui := state.Get("ui").(packer.Ui) 32 vmName := state.Get("vmName").(string) 33 34 if s.Command != "" { 35 ui.Say("Gracefully halting virtual machine...") 36 log.Printf("Executing shutdown command: %s", s.Command) 37 cmd := &packer.RemoteCmd{Command: s.Command} 38 if err := cmd.StartWithUi(comm, ui); err != nil { 39 err := fmt.Errorf("Failed to send shutdown command: %s", err) 40 state.Put("error", err) 41 ui.Error(err.Error()) 42 return multistep.ActionHalt 43 } 44 45 // Wait for the machine to actually shut down 46 log.Printf("Waiting max %s for shutdown to complete", s.Timeout) 47 shutdownTimer := time.After(s.Timeout) 48 for { 49 running, _ := driver.IsRunning(vmName) 50 if !running { 51 break 52 } 53 54 select { 55 case <-shutdownTimer: 56 err := errors.New("Timeout while waiting for machine to shut down.") 57 state.Put("error", err) 58 ui.Error(err.Error()) 59 return multistep.ActionHalt 60 default: 61 time.Sleep(500 * time.Millisecond) 62 } 63 } 64 } else { 65 ui.Say("Halting the virtual machine...") 66 if err := driver.Stop(vmName); err != nil { 67 err := fmt.Errorf("Error stopping VM: %s", err) 68 state.Put("error", err) 69 ui.Error(err.Error()) 70 return multistep.ActionHalt 71 } 72 } 73 74 log.Println("VM shut down.") 75 return multistep.ActionContinue 76 } 77 78 func (s *StepShutdown) Cleanup(state multistep.StateBag) {}