github.com/raghuse92/packer@v1.3.2/builder/qemu/step_shutdown.go (about) 1 package qemu 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "log" 8 "time" 9 10 "github.com/hashicorp/packer/helper/multistep" 11 "github.com/hashicorp/packer/packer" 12 ) 13 14 // This step shuts down the machine. It first attempts to do so gracefully, 15 // but ultimately forcefully shuts it down if that fails. 16 // 17 // Uses: 18 // communicator packer.Communicator 19 // config *config 20 // driver Driver 21 // ui packer.Ui 22 // 23 // Produces: 24 // <nothing> 25 type stepShutdown struct{} 26 27 func (s *stepShutdown) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { 28 config := state.Get("config").(*Config) 29 driver := state.Get("driver").(Driver) 30 ui := state.Get("ui").(packer.Ui) 31 32 if state.Get("communicator") == nil { 33 cancelCh := make(chan struct{}, 1) 34 go func() { 35 defer close(cancelCh) 36 <-time.After(config.shutdownTimeout) 37 }() 38 ui.Say("Waiting for shutdown...") 39 if ok := driver.WaitForShutdown(cancelCh); ok { 40 log.Println("VM shut down.") 41 return multistep.ActionContinue 42 } else { 43 err := fmt.Errorf("Failed to shutdown") 44 state.Put("error", err) 45 ui.Error(err.Error()) 46 return multistep.ActionHalt 47 } 48 } 49 50 comm := state.Get("communicator").(packer.Communicator) 51 if config.ShutdownCommand != "" { 52 ui.Say("Gracefully halting virtual machine...") 53 log.Printf("Executing shutdown command: %s", config.ShutdownCommand) 54 cmd := &packer.RemoteCmd{Command: config.ShutdownCommand} 55 if err := cmd.StartWithUi(comm, ui); err != nil { 56 err := fmt.Errorf("Failed to send shutdown command: %s", err) 57 state.Put("error", err) 58 ui.Error(err.Error()) 59 return multistep.ActionHalt 60 } 61 62 // Start the goroutine that will time out our graceful attempt 63 cancelCh := make(chan struct{}, 1) 64 go func() { 65 defer close(cancelCh) 66 <-time.After(config.shutdownTimeout) 67 }() 68 69 log.Printf("Waiting max %s for shutdown to complete", config.shutdownTimeout) 70 if ok := driver.WaitForShutdown(cancelCh); !ok { 71 err := errors.New("Timeout while waiting for machine to shut down.") 72 state.Put("error", err) 73 ui.Error(err.Error()) 74 return multistep.ActionHalt 75 } 76 } else { 77 ui.Say("Halting the virtual machine...") 78 if err := driver.Stop(); err != nil { 79 err := fmt.Errorf("Error stopping VM: %s", err) 80 state.Put("error", err) 81 ui.Error(err.Error()) 82 return multistep.ActionHalt 83 } 84 } 85 86 log.Println("VM shut down.") 87 return multistep.ActionContinue 88 } 89 90 func (s *stepShutdown) Cleanup(state multistep.StateBag) {}