github.com/raghuse92/packer@v1.3.2/builder/openstack/step_create_volume.go (about) 1 package openstack 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes" 8 "github.com/hashicorp/packer/helper/multistep" 9 "github.com/hashicorp/packer/packer" 10 ) 11 12 type StepCreateVolume struct { 13 UseBlockStorageVolume bool 14 VolumeName string 15 VolumeType string 16 VolumeAvailabilityZone string 17 volumeID string 18 doCleanup bool 19 } 20 21 func (s *StepCreateVolume) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { 22 // Proceed only if block storage volume is required. 23 if !s.UseBlockStorageVolume { 24 return multistep.ActionContinue 25 } 26 27 config := state.Get("config").(*Config) 28 ui := state.Get("ui").(packer.Ui) 29 sourceImage := state.Get("source_image").(string) 30 31 // We will need Block Storage and Image services clients. 32 blockStorageClient, err := config.blockStorageV3Client() 33 if err != nil { 34 err = fmt.Errorf("Error initializing block storage client: %s", err) 35 state.Put("error", err) 36 return multistep.ActionHalt 37 } 38 imageClient, err := config.imageV2Client() 39 if err != nil { 40 err = fmt.Errorf("Error initializing image client: %s", err) 41 state.Put("error", err) 42 return multistep.ActionHalt 43 } 44 45 // Get needed volume size from the source image. 46 volumeSize, err := GetVolumeSize(imageClient, sourceImage) 47 if err != nil { 48 err := fmt.Errorf("Error creating volume: %s", err) 49 state.Put("error", err) 50 ui.Error(err.Error()) 51 return multistep.ActionHalt 52 } 53 54 ui.Say("Creating volume...") 55 volumeOpts := volumes.CreateOpts{ 56 Size: volumeSize, 57 VolumeType: s.VolumeType, 58 AvailabilityZone: s.VolumeAvailabilityZone, 59 Name: s.VolumeName, 60 ImageID: sourceImage, 61 } 62 volume, err := volumes.Create(blockStorageClient, volumeOpts).Extract() 63 if err != nil { 64 err := fmt.Errorf("Error creating volume: %s", err) 65 state.Put("error", err) 66 ui.Error(err.Error()) 67 return multistep.ActionHalt 68 } 69 70 // Wait for volume to become available. 71 ui.Say(fmt.Sprintf("Waiting for volume %s (volume id: %s) to become available...", config.VolumeName, volume.ID)) 72 if err := WaitForVolume(blockStorageClient, volume.ID); err != nil { 73 err := fmt.Errorf("Error waiting for volume: %s", err) 74 state.Put("error", err) 75 ui.Error(err.Error()) 76 return multistep.ActionHalt 77 } 78 79 // Volume was created, so remember to clean it up. 80 s.doCleanup = true 81 82 // Set the Volume ID in the state. 83 ui.Message(fmt.Sprintf("Volume ID: %s", volume.ID)) 84 state.Put("volume_id", volume.ID) 85 s.volumeID = volume.ID 86 87 return multistep.ActionContinue 88 } 89 90 func (s *StepCreateVolume) Cleanup(state multistep.StateBag) { 91 if !s.doCleanup { 92 return 93 } 94 95 config := state.Get("config").(*Config) 96 ui := state.Get("ui").(packer.Ui) 97 98 blockStorageClient, err := config.blockStorageV3Client() 99 if err != nil { 100 ui.Error(fmt.Sprintf( 101 "Error cleaning up volume. Please delete the volume manually: %s", s.volumeID)) 102 return 103 } 104 105 // Wait for volume to become available. 106 status, err := GetVolumeStatus(blockStorageClient, s.volumeID) 107 if err != nil { 108 ui.Error(fmt.Sprintf( 109 "Error getting the volume information. Please delete the volume manually: %s", s.volumeID)) 110 return 111 } 112 113 if status != "available" { 114 ui.Say(fmt.Sprintf( 115 "Waiting for volume %s (volume id: %s) to become available...", s.VolumeName, s.volumeID)) 116 if err := WaitForVolume(blockStorageClient, s.volumeID); err != nil { 117 ui.Error(fmt.Sprintf( 118 "Error getting the volume information. Please delete the volume manually: %s", s.volumeID)) 119 return 120 } 121 } 122 ui.Say(fmt.Sprintf("Deleting volume: %s ...", s.volumeID)) 123 err = volumes.Delete(blockStorageClient, s.volumeID).ExtractErr() 124 if err != nil { 125 ui.Error(fmt.Sprintf( 126 "Error cleaning up volume. Please delete the volume manually: %s", s.volumeID)) 127 } 128 }