github.com/rahart/packer@v0.12.2-0.20161229105310-282bb6ad370f/builder/hyperv/common/step_shutdown.go (about) 1 package common 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "github.com/mitchellh/multistep" 8 "github.com/mitchellh/packer/packer" 9 "log" 10 "time" 11 ) 12 13 // This step shuts down the machine. It first attempts to do so gracefully, 14 // but ultimately forcefully shuts it down if that fails. 15 // 16 // Uses: 17 // communicator packer.Communicator 18 // dir OutputDir 19 // driver Driver 20 // ui packer.Ui 21 // vmx_path string 22 // 23 // Produces: 24 // <nothing> 25 type StepShutdown struct { 26 Command string 27 Timeout time.Duration 28 } 29 30 func (s *StepShutdown) Run(state multistep.StateBag) multistep.StepAction { 31 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 command to run so we can print std{err,out} 55 // We don't care if the command errored, since we'll notice 56 // if the vm didn't shut down. 57 cmd.Wait() 58 59 log.Printf("Shutdown stdout: %s", stdout.String()) 60 log.Printf("Shutdown stderr: %s", stderr.String()) 61 62 // Wait for the machine to actually shut down 63 log.Printf("Waiting max %s for shutdown to complete", s.Timeout) 64 shutdownTimer := time.After(s.Timeout) 65 for { 66 running, _ := driver.IsRunning(vmName) 67 if !running { 68 break 69 } 70 71 select { 72 case <-shutdownTimer: 73 err := errors.New("Timeout while waiting for machine to shut down.") 74 state.Put("error", err) 75 ui.Error(err.Error()) 76 return multistep.ActionHalt 77 default: 78 time.Sleep(150 * time.Millisecond) 79 } 80 } 81 } else { 82 ui.Say("Forcibly halting virtual machine...") 83 if err := driver.Stop(vmName); err != nil { 84 err := fmt.Errorf("Error stopping VM: %s", err) 85 state.Put("error", err) 86 ui.Error(err.Error()) 87 return multistep.ActionHalt 88 } 89 } 90 91 log.Println("VM shut down.") 92 return multistep.ActionContinue 93 } 94 95 func (s *StepShutdown) Cleanup(state multistep.StateBag) {}