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