github.com/emate/packer@v0.8.1-0.20150625195101-fe0fde195dc6/builder/digitalocean/step_snapshot.go (about)

     1  package digitalocean
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"log"
     7  	"time"
     8  
     9  	"github.com/digitalocean/godo"
    10  	"github.com/mitchellh/multistep"
    11  	"github.com/mitchellh/packer/packer"
    12  )
    13  
    14  type stepSnapshot struct{}
    15  
    16  func (s *stepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
    17  	client := state.Get("client").(*godo.Client)
    18  	ui := state.Get("ui").(packer.Ui)
    19  	c := state.Get("config").(Config)
    20  	dropletId := state.Get("droplet_id").(int)
    21  
    22  	ui.Say(fmt.Sprintf("Creating snapshot: %v", c.SnapshotName))
    23  	_, _, err := client.DropletActions.Snapshot(dropletId, c.SnapshotName)
    24  	if err != nil {
    25  		err := fmt.Errorf("Error creating snapshot: %s", err)
    26  		state.Put("error", err)
    27  		ui.Error(err.Error())
    28  		return multistep.ActionHalt
    29  	}
    30  
    31  	// Wait for the droplet to become unlocked first. For snapshots
    32  	// this can end up taking quite a long time, so we hardcode this to
    33  	// 10 minutes.
    34  	if err := waitForDropletUnlocked(client, dropletId, 10*time.Minute); err != nil {
    35  		// If we get an error the first time, actually report it
    36  		err := fmt.Errorf("Error shutting down droplet: %s", err)
    37  		state.Put("error", err)
    38  		ui.Error(err.Error())
    39  		return multistep.ActionHalt
    40  	}
    41  
    42  	// With the pending state over, verify that we're in the active state
    43  	ui.Say("Waiting for snapshot to complete...")
    44  	err = waitForDropletState("active", dropletId, client, c.StateTimeout)
    45  	if err != nil {
    46  		err := fmt.Errorf("Error waiting for snapshot to complete: %s", err)
    47  		state.Put("error", err)
    48  		ui.Error(err.Error())
    49  		return multistep.ActionHalt
    50  	}
    51  
    52  	log.Printf("Looking up snapshot ID for snapshot: %s", c.SnapshotName)
    53  	images, _, err := client.Images.ListUser(&godo.ListOptions{PerPage: 200})
    54  	if err != nil {
    55  		err := fmt.Errorf("Error looking up snapshot ID: %s", err)
    56  		state.Put("error", err)
    57  		ui.Error(err.Error())
    58  		return multistep.ActionHalt
    59  	}
    60  
    61  	var imageId int
    62  	for _, image := range images {
    63  		if image.Name == c.SnapshotName {
    64  			imageId = image.ID
    65  			break
    66  		}
    67  	}
    68  
    69  	if imageId == 0 {
    70  		err := errors.New("Couldn't find snapshot to get the image ID. Bug?")
    71  		state.Put("error", err)
    72  		ui.Error(err.Error())
    73  		return multistep.ActionHalt
    74  	}
    75  
    76  	log.Printf("Snapshot image ID: %d", imageId)
    77  	state.Put("snapshot_image_id", imageId)
    78  	state.Put("snapshot_name", c.SnapshotName)
    79  	state.Put("region", c.Region)
    80  
    81  	return multistep.ActionContinue
    82  }
    83  
    84  func (s *stepSnapshot) Cleanup(state multistep.StateBag) {
    85  	// no cleanup
    86  }