github.phpd.cn/hashicorp/packer@v1.3.2/builder/openstack/volume.go (about) 1 package openstack 2 3 import ( 4 "log" 5 "time" 6 7 "github.com/gophercloud/gophercloud" 8 "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes" 9 "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images" 10 ) 11 12 // WaitForVolume waits for the given volume to become available. 13 func WaitForVolume(blockStorageClient *gophercloud.ServiceClient, volumeID string) error { 14 maxNumErrors := 10 15 numErrors := 0 16 17 for { 18 status, err := GetVolumeStatus(blockStorageClient, volumeID) 19 if err != nil { 20 errCode, ok := err.(*gophercloud.ErrUnexpectedResponseCode) 21 if ok && (errCode.Actual == 500 || errCode.Actual == 404) { 22 numErrors++ 23 if numErrors >= maxNumErrors { 24 log.Printf("[ERROR] Maximum number of errors (%d) reached; failing with: %s", numErrors, err) 25 return err 26 } 27 log.Printf("[ERROR] %d error received, will ignore and retry: %s", errCode.Actual, err) 28 time.Sleep(2 * time.Second) 29 continue 30 } 31 32 return err 33 } 34 35 if status == "available" { 36 return nil 37 } 38 39 log.Printf("Waiting for volume creation status: %s", status) 40 time.Sleep(2 * time.Second) 41 } 42 } 43 44 // GetVolumeSize returns volume size in gigabytes based on the image min disk 45 // value if it's not empty. 46 // Or it calculates needed gigabytes size from the image bytes size. 47 func GetVolumeSize(imageClient *gophercloud.ServiceClient, imageID string) (int, error) { 48 sourceImage, err := images.Get(imageClient, imageID).Extract() 49 if err != nil { 50 return 0, err 51 } 52 53 if sourceImage.MinDiskGigabytes != 0 { 54 return sourceImage.MinDiskGigabytes, nil 55 } 56 57 volumeSizeMB := sourceImage.SizeBytes / 1024 / 1024 58 volumeSizeGB := int(sourceImage.SizeBytes / 1024 / 1024 / 1024) 59 60 // Increment gigabytes size if the initial size can't be divided without 61 // remainder. 62 if volumeSizeMB%1024 > 0 { 63 volumeSizeGB++ 64 } 65 66 return volumeSizeGB, nil 67 } 68 69 func GetVolumeStatus(blockStorageClient *gophercloud.ServiceClient, volumeID string) (string, error) { 70 volume, err := volumes.Get(blockStorageClient, volumeID).Extract() 71 if err != nil { 72 return "", err 73 } 74 75 return volume.Status, nil 76 }