github.com/amanya/packer@v0.12.1-0.20161117214323-902ac5ab2eb6/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  	action, _, 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  	// With the pending state over, verify that we're in the active state
    32  	ui.Say("Waiting for snapshot to complete...")
    33  	if err := waitForActionState(godo.ActionCompleted, dropletId, action.ID,
    34  		client, 20*time.Minute); err != nil {
    35  		// If we get an error the first time, actually report it
    36  		err := fmt.Errorf("Error waiting for snapshot: %s", err)
    37  		state.Put("error", err)
    38  		ui.Error(err.Error())
    39  		return multistep.ActionHalt
    40  	}
    41  
    42  	// Wait for the droplet to become unlocked first. For snapshots
    43  	// this can end up taking quite a long time, so we hardcode this to
    44  	// 20 minutes.
    45  	if err := waitForDropletUnlocked(client, dropletId, 20*time.Minute); err != nil {
    46  		// If we get an error the first time, actually report it
    47  		err := fmt.Errorf("Error shutting down droplet: %s", err)
    48  		state.Put("error", err)
    49  		ui.Error(err.Error())
    50  		return multistep.ActionHalt
    51  	}
    52  
    53  	log.Printf("Looking up snapshot ID for snapshot: %s", c.SnapshotName)
    54  	images, _, err := client.Droplets.Snapshots(dropletId, nil)
    55  	if err != nil {
    56  		err := fmt.Errorf("Error looking up snapshot ID: %s", err)
    57  		state.Put("error", err)
    58  		ui.Error(err.Error())
    59  		return multistep.ActionHalt
    60  	}
    61  
    62  	var imageId int
    63  	if len(images) == 1 {
    64  		imageId = images[0].ID
    65  	} else {
    66  		err := errors.New("Couldn't find snapshot to get the image ID. Bug?")
    67  		state.Put("error", err)
    68  		ui.Error(err.Error())
    69  		return multistep.ActionHalt
    70  	}
    71  
    72  	log.Printf("Snapshot image ID: %d", imageId)
    73  	state.Put("snapshot_image_id", imageId)
    74  	state.Put("snapshot_name", c.SnapshotName)
    75  	state.Put("region", c.Region)
    76  
    77  	return multistep.ActionContinue
    78  }
    79  
    80  func (s *stepSnapshot) Cleanup(state multistep.StateBag) {
    81  	// no cleanup
    82  }