github.com/StackPointCloud/packer@v0.10.2-0.20180716202532-b28098e0f79b/builder/amazon/chroot/step_create_volume.go (about) 1 package chroot 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 8 "github.com/aws/aws-sdk-go/aws" 9 "github.com/aws/aws-sdk-go/service/ec2" 10 awscommon "github.com/hashicorp/packer/builder/amazon/common" 11 "github.com/hashicorp/packer/helper/multistep" 12 "github.com/hashicorp/packer/packer" 13 ) 14 15 // StepCreateVolume creates a new volume from the snapshot of the root 16 // device of the AMI. 17 // 18 // Produces: 19 // volume_id string - The ID of the created volume 20 type StepCreateVolume struct { 21 volumeId string 22 RootVolumeSize int64 23 } 24 25 func (s *StepCreateVolume) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { 26 config := state.Get("config").(*Config) 27 ec2conn := state.Get("ec2").(*ec2.EC2) 28 instance := state.Get("instance").(*ec2.Instance) 29 ui := state.Get("ui").(packer.Ui) 30 31 var createVolume *ec2.CreateVolumeInput 32 if config.FromScratch { 33 createVolume = &ec2.CreateVolumeInput{ 34 AvailabilityZone: instance.Placement.AvailabilityZone, 35 Size: aws.Int64(s.RootVolumeSize), 36 VolumeType: aws.String(ec2.VolumeTypeGp2), 37 } 38 } else { 39 // Determine the root device snapshot 40 image := state.Get("source_image").(*ec2.Image) 41 log.Printf("Searching for root device of the image (%s)", *image.RootDeviceName) 42 var rootDevice *ec2.BlockDeviceMapping 43 for _, device := range image.BlockDeviceMappings { 44 if *device.DeviceName == *image.RootDeviceName { 45 rootDevice = device 46 break 47 } 48 } 49 50 if rootDevice == nil { 51 err := fmt.Errorf("Couldn't find root device!") 52 state.Put("error", err) 53 ui.Error(err.Error()) 54 return multistep.ActionHalt 55 } 56 57 ui.Say("Creating the root volume...") 58 vs := *rootDevice.Ebs.VolumeSize 59 if s.RootVolumeSize > *rootDevice.Ebs.VolumeSize { 60 vs = s.RootVolumeSize 61 } 62 63 createVolume = &ec2.CreateVolumeInput{ 64 AvailabilityZone: instance.Placement.AvailabilityZone, 65 Size: aws.Int64(vs), 66 SnapshotId: rootDevice.Ebs.SnapshotId, 67 VolumeType: rootDevice.Ebs.VolumeType, 68 Iops: rootDevice.Ebs.Iops, 69 } 70 } 71 72 log.Printf("Create args: %+v", createVolume) 73 74 createVolumeResp, err := ec2conn.CreateVolume(createVolume) 75 if err != nil { 76 err := fmt.Errorf("Error creating root volume: %s", err) 77 state.Put("error", err) 78 ui.Error(err.Error()) 79 return multistep.ActionHalt 80 } 81 82 // Set the volume ID so we remember to delete it later 83 s.volumeId = *createVolumeResp.VolumeId 84 log.Printf("Volume ID: %s", s.volumeId) 85 86 // Wait for the volume to become ready 87 err = awscommon.WaitUntilVolumeAvailable(ctx, ec2conn, s.volumeId) 88 if err != nil { 89 err := fmt.Errorf("Error waiting for volume: %s", err) 90 state.Put("error", err) 91 ui.Error(err.Error()) 92 return multistep.ActionHalt 93 } 94 95 state.Put("volume_id", s.volumeId) 96 return multistep.ActionContinue 97 } 98 99 func (s *StepCreateVolume) Cleanup(state multistep.StateBag) { 100 if s.volumeId == "" { 101 return 102 } 103 104 ec2conn := state.Get("ec2").(*ec2.EC2) 105 ui := state.Get("ui").(packer.Ui) 106 107 ui.Say("Deleting the created EBS volume...") 108 _, err := ec2conn.DeleteVolume(&ec2.DeleteVolumeInput{VolumeId: &s.volumeId}) 109 if err != nil { 110 ui.Error(fmt.Sprintf("Error deleting EBS volume: %s", err)) 111 } 112 }