github.com/askholme/packer@v0.7.2-0.20140924152349-70d9566a6852/builder/amazon/chroot/step_snapshot.go (about)

     1  package chroot
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/mitchellh/goamz/ec2"
     9  	"github.com/mitchellh/multistep"
    10  	awscommon "github.com/mitchellh/packer/builder/amazon/common"
    11  	"github.com/mitchellh/packer/packer"
    12  )
    13  
    14  // StepSnapshot creates a snapshot of the created volume.
    15  //
    16  // Produces:
    17  //   snapshot_id string - ID of the created snapshot
    18  type StepSnapshot struct {
    19  	snapshotId string
    20  }
    21  
    22  func (s *StepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
    23  	ec2conn := state.Get("ec2").(*ec2.EC2)
    24  	ui := state.Get("ui").(packer.Ui)
    25  	volumeId := state.Get("volume_id").(string)
    26  
    27  	ui.Say("Creating snapshot...")
    28  	createSnapResp, err := ec2conn.CreateSnapshot(
    29  		volumeId,
    30  		fmt.Sprintf("Packer: %s", time.Now().String()))
    31  	if err != nil {
    32  		err := fmt.Errorf("Error creating snapshot: %s", err)
    33  		state.Put("error", err)
    34  		ui.Error(err.Error())
    35  		return multistep.ActionHalt
    36  	}
    37  
    38  	// Set the snapshot ID so we can delete it later
    39  	s.snapshotId = createSnapResp.Id
    40  	ui.Message(fmt.Sprintf("Snapshot ID: %s", s.snapshotId))
    41  
    42  	// Wait for the snapshot to be ready
    43  	stateChange := awscommon.StateChangeConf{
    44  		Pending:   []string{"pending"},
    45  		StepState: state,
    46  		Target:    "completed",
    47  		Refresh: func() (interface{}, string, error) {
    48  			resp, err := ec2conn.Snapshots([]string{s.snapshotId}, ec2.NewFilter())
    49  			if err != nil {
    50  				return nil, "", err
    51  			}
    52  
    53  			if len(resp.Snapshots) == 0 {
    54  				return nil, "", errors.New("No snapshots found.")
    55  			}
    56  
    57  			s := resp.Snapshots[0]
    58  			return s, s.Status, nil
    59  		},
    60  	}
    61  
    62  	_, err = awscommon.WaitForState(&stateChange)
    63  	if err != nil {
    64  		err := fmt.Errorf("Error waiting for snapshot: %s", err)
    65  		state.Put("error", err)
    66  		ui.Error(err.Error())
    67  		return multistep.ActionHalt
    68  	}
    69  
    70  	state.Put("snapshot_id", s.snapshotId)
    71  	return multistep.ActionContinue
    72  }
    73  
    74  func (s *StepSnapshot) Cleanup(state multistep.StateBag) {
    75  	if s.snapshotId == "" {
    76  		return
    77  	}
    78  
    79  	_, cancelled := state.GetOk(multistep.StateCancelled)
    80  	_, halted := state.GetOk(multistep.StateHalted)
    81  
    82  	if cancelled || halted {
    83  		ec2conn := state.Get("ec2").(*ec2.EC2)
    84  		ui := state.Get("ui").(packer.Ui)
    85  		ui.Say("Removing snapshot since we cancelled or halted...")
    86  		_, err := ec2conn.DeleteSnapshots([]string{s.snapshotId})
    87  		if err != nil {
    88  			ui.Error(fmt.Sprintf("Error: %s", err))
    89  		}
    90  	}
    91  }