github.com/sneal/packer@v0.5.2/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 multistep.StateBag) multistep.StepAction { 22 ec2conn := state.Get("ec2").(*ec2.EC2) 23 image := state.Get("source_image").(*ec2.Image) 24 instance := state.Get("instance").(*ec2.Instance) 25 ui := state.Get("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.Put("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.Put("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 Pending: []string{"creating"}, 69 StepState: state, 70 Target: "available", 71 Refresh: func() (interface{}, string, error) { 72 resp, err := ec2conn.Volumes([]string{s.volumeId}, ec2.NewFilter()) 73 if err != nil { 74 return nil, "", err 75 } 76 77 v := resp.Volumes[0] 78 return v, v.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.Put("error", err) 86 ui.Error(err.Error()) 87 return multistep.ActionHalt 88 } 89 90 state.Put("volume_id", s.volumeId) 91 return multistep.ActionContinue 92 } 93 94 func (s *StepCreateVolume) Cleanup(state multistep.StateBag) { 95 if s.volumeId == "" { 96 return 97 } 98 99 ec2conn := state.Get("ec2").(*ec2.EC2) 100 ui := state.Get("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 }