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 }