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