github.com/emate/packer@v0.8.1-0.20150625195101-fe0fde195dc6/builder/openstack/step_create_image.go (about) 1 package openstack 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/mitchellh/multistep" 9 "github.com/mitchellh/packer/packer" 10 "github.com/rackspace/gophercloud" 11 "github.com/rackspace/gophercloud/openstack/compute/v2/images" 12 "github.com/rackspace/gophercloud/openstack/compute/v2/servers" 13 ) 14 15 type stepCreateImage struct{} 16 17 func (s *stepCreateImage) Run(state multistep.StateBag) multistep.StepAction { 18 config := state.Get("config").(Config) 19 server := state.Get("server").(*servers.Server) 20 ui := state.Get("ui").(packer.Ui) 21 22 // We need the v2 compute client 23 client, err := config.computeV2Client() 24 if err != nil { 25 err = fmt.Errorf("Error initializing compute client: %s", err) 26 state.Put("error", err) 27 return multistep.ActionHalt 28 } 29 30 // Create the image 31 ui.Say(fmt.Sprintf("Creating the image: %s", config.ImageName)) 32 imageId, err := servers.CreateImage(client, server.ID, servers.CreateImageOpts{ 33 Name: config.ImageName, 34 }).ExtractImageID() 35 if err != nil { 36 err := fmt.Errorf("Error creating image: %s", err) 37 state.Put("error", err) 38 ui.Error(err.Error()) 39 return multistep.ActionHalt 40 } 41 42 // Set the Image ID in the state 43 ui.Message(fmt.Sprintf("Image: %s", imageId)) 44 state.Put("image", imageId) 45 46 // Wait for the image to become ready 47 ui.Say("Waiting for image to become ready...") 48 if err := WaitForImage(client, imageId); err != nil { 49 err := fmt.Errorf("Error waiting for image: %s", err) 50 state.Put("error", err) 51 ui.Error(err.Error()) 52 return multistep.ActionHalt 53 } 54 55 return multistep.ActionContinue 56 } 57 58 func (s *stepCreateImage) Cleanup(multistep.StateBag) { 59 // No cleanup... 60 } 61 62 // WaitForImage waits for the given Image ID to become ready. 63 func WaitForImage(client *gophercloud.ServiceClient, imageId string) error { 64 for { 65 image, err := images.Get(client, imageId).Extract() 66 if err != nil { 67 errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) 68 if ok && errCode.Actual == 500 { 69 log.Printf("[ERROR] 500 error received, will ignore and retry: %s", err) 70 time.Sleep(2 * time.Second) 71 continue 72 } 73 74 return err 75 } 76 77 if image.Status == "ACTIVE" { 78 return nil 79 } 80 81 log.Printf("Waiting for image creation status: %s (%d%%)", image.Status, image.Progress) 82 time.Sleep(2 * time.Second) 83 } 84 }