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