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) {}