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 }