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