github.com/phobos182/packer@v0.2.3-0.20130819023704-c84d2aeffc68/builder/amazon/chroot/step_create_volume.go (about)

     1  package chroot
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/mitchellh/goamz/ec2"
     6  	"github.com/mitchellh/multistep"
     7  	awscommon "github.com/mitchellh/packer/builder/amazon/common"
     8  	"github.com/mitchellh/packer/packer"
     9  	"log"
    10  )
    11  
    12  // StepCreateVolume creates a new volume from the snapshot of the root
    13  // device of the AMI.
    14  //
    15  // Produces:
    16  //   volume_id string - The ID of the created volume
    17  type StepCreateVolume struct {
    18  	volumeId string
    19  }
    20  
    21  func (s *StepCreateVolume) Run(state map[string]interface{}) multistep.StepAction {
    22  	ec2conn := state["ec2"].(*ec2.EC2)
    23  	image := state["source_image"].(*ec2.Image)
    24  	instance := state["instance"].(*ec2.Instance)
    25  	ui := state["ui"].(packer.Ui)
    26  
    27  	// Determine the root device snapshot
    28  	log.Printf("Searching for root device of the image (%s)", image.RootDeviceName)
    29  	var rootDevice *ec2.BlockDeviceMapping
    30  	for _, device := range image.BlockDevices {
    31  		if device.DeviceName == image.RootDeviceName {
    32  			rootDevice = &device
    33  			break
    34  		}
    35  	}
    36  
    37  	if rootDevice == nil {
    38  		err := fmt.Errorf("Couldn't find root device!")
    39  		state["error"] = err
    40  		ui.Error(err.Error())
    41  		return multistep.ActionHalt
    42  	}
    43  
    44  	ui.Say("Creating the root volume...")
    45  	createVolume := &ec2.CreateVolume{
    46  		AvailZone:  instance.AvailZone,
    47  		Size:       rootDevice.VolumeSize,
    48  		SnapshotId: rootDevice.SnapshotId,
    49  		VolumeType: rootDevice.VolumeType,
    50  		IOPS:       rootDevice.IOPS,
    51  	}
    52  	log.Printf("Create args: %#v", createVolume)
    53  
    54  	createVolumeResp, err := ec2conn.CreateVolume(createVolume)
    55  	if err != nil {
    56  		err := fmt.Errorf("Error creating root volume: %s", err)
    57  		state["error"] = err
    58  		ui.Error(err.Error())
    59  		return multistep.ActionHalt
    60  	}
    61  
    62  	// Set the volume ID so we remember to delete it later
    63  	s.volumeId = createVolumeResp.VolumeId
    64  	log.Printf("Volume ID: %s", s.volumeId)
    65  
    66  	// Wait for the volume to become ready
    67  	stateChange := awscommon.StateChangeConf{
    68  		Conn:      ec2conn,
    69  		Pending:   []string{"creating"},
    70  		StepState: state,
    71  		Target:    "available",
    72  		Refresh: func() (interface{}, string, error) {
    73  			resp, err := ec2conn.Volumes([]string{s.volumeId}, ec2.NewFilter())
    74  			if err != nil {
    75  				return nil, "", err
    76  			}
    77  
    78  			return nil, resp.Volumes[0].Status, nil
    79  		},
    80  	}
    81  
    82  	_, err = awscommon.WaitForState(&stateChange)
    83  	if err != nil {
    84  		err := fmt.Errorf("Error waiting for volume: %s", err)
    85  		state["error"] = err
    86  		ui.Error(err.Error())
    87  		return multistep.ActionHalt
    88  	}
    89  
    90  	state["volume_id"] = s.volumeId
    91  	return multistep.ActionContinue
    92  }
    93  
    94  func (s *StepCreateVolume) Cleanup(state map[string]interface{}) {
    95  	if s.volumeId == "" {
    96  		return
    97  	}
    98  
    99  	ec2conn := state["ec2"].(*ec2.EC2)
   100  	ui := state["ui"].(packer.Ui)
   101  
   102  	ui.Say("Deleting the created EBS volume...")
   103  	_, err := ec2conn.DeleteVolume(s.volumeId)
   104  	if err != nil {
   105  		ui.Error(fmt.Sprintf("Error deleting EBS volume: %s", err))
   106  	}
   107  }