@@ -22,6 +22,7 @@ import (
2222 "errors"
2323 "fmt"
2424 "time"
25+ "sync"
2526
2627 "github.com/gophercloud/gophercloud"
2728 "github.com/gophercloud/gophercloud/openstack"
@@ -147,74 +148,104 @@ func (r *OpenStackNodeImageReleaseReconciler) Reconcile(ctx context.Context, req
147148 cloudName string = openstacknodeimagerelease .Spec .CloudName
148149 imageName string = openstacknodeimagerelease .Spec .Name
149150 imageURL string = openstacknodeimagerelease .Spec .URL
151+ containerFormat string = openstacknodeimagerelease .Spec .ContainerFormat
152+ diskFormat string = openstacknodeimagerelease .Spec .DiskFormat
150153 )
151154
152- cloud , err := getCloudFromSecret (ctx , r .Client , secretNamespace , secretName , cloudName )
153- if err != nil {
154- return ctrl.Result {}, err
155- }
156-
157- // Authenticate
158- authOpts := gophercloud.AuthOptions {
159- IdentityEndpoint : cloud .AuthInfo .AuthURL ,
160- Username : cloud .AuthInfo .Username ,
161- Password : cloud .AuthInfo .Password ,
162- DomainName : cloud .AuthInfo .UserDomainName ,
163- TenantID : cloud .AuthInfo .ProjectID ,
164- }
155+ // Create a channel to receive errors from the goroutine
156+ resultChan := make (chan error , 1 )
157+ // Create a wait group to wait for all goroutines to finish
158+ var wg sync.WaitGroup
159+
160+ // Function to do import image concurrently, needs to be modified probably, still testing it
161+ downloadImage := func () {
162+ defer wg .Done () // Decrement the wait group counter when the goroutine completes
163+ cloud , err := getCloudFromSecret (ctx , r .Client , secretNamespace , secretName , cloudName )
164+ if err != nil {
165+ // Handle error
166+ resultChan <- err
167+ return
168+ }
165169
166- provider , err := openstack .AuthenticatedClient (authOpts )
167- if err != nil {
168- return ctrl.Result {}, fmt .Errorf ("Error authenticating with OpenStack: %w" , err )
169- }
170+ // Authenticate
171+ authOpts := gophercloud.AuthOptions {
172+ IdentityEndpoint : cloud .AuthInfo .AuthURL ,
173+ Username : cloud .AuthInfo .Username ,
174+ Password : cloud .AuthInfo .Password ,
175+ DomainName : cloud .AuthInfo .UserDomainName ,
176+ TenantID : cloud .AuthInfo .ProjectID ,
177+ }
170178
171- // Create an Image service client
172- imageClient , err := openstack .NewImageServiceV2 (provider , gophercloud.EndpointOpts {
173- Region : cloud .RegionName ,
174- })
179+ provider , err := openstack .AuthenticatedClient (authOpts )
180+ if err != nil {
181+ // Handle error
182+ resultChan <- err
183+ return
184+ }
175185
176- imageID , err := findImageByName (imageClient , imageName )
177- if err != nil {
178- return ctrl.Result {}, fmt .Errorf ("Error finding image: %w" , err )
179- } else {
180- if imageID == "" {
181- visibility := images .ImageVisibilityShared
182-
183- createOptsImage := images.CreateOpts {
184- Name : imageName ,
185- ContainerFormat : "bare" ,
186- DiskFormat : "iso" ,
187- Visibility : & visibility ,
188- }
186+ // Create an Image service client
187+ imageClient , err := openstack .NewImageServiceV2 (provider , gophercloud.EndpointOpts {
188+ Region : cloud .RegionName ,
189+ })
190+
191+ imageID , err := findImageByName (imageClient , imageName )
192+ if err != nil {
193+ resultChan <- fmt .Errorf ("Error finding image: %w" , err )
194+ return
195+ } else {
196+ if imageID == "" {
197+ visibility := images .ImageVisibilityShared
198+
199+ createOptsImage := images.CreateOpts {
200+ Name : imageName ,
201+ ContainerFormat : containerFormat ,
202+ DiskFormat : diskFormat ,
203+ Visibility : & visibility ,
204+ }
189205
190- image , err := createImage (imageClient , createOptsImage )
191- if err != nil {
192- return ctrl.Result {Requeue : true }, err
193- }
206+ image , err := createImage (imageClient , createOptsImage )
207+ if err != nil {
208+ // Handle error
209+ logger .Error (err , "Failed to find or create image" )
210+ return
211+ }
194212
195- createOpts := imageimport.CreateOpts {
196- Name : imageimport .WebDownloadMethod ,
197- URI : imageURL ,
198- }
199- imageID = image .ID
213+ createOpts := imageimport.CreateOpts {
214+ Name : imageimport .WebDownloadMethod ,
215+ URI : imageURL ,
216+ }
217+ imageID = image .ID
200218
201- // Handle error during image import
202- err = importImage (imageClient , image .ID , createOpts )
203- if err != nil {
204- return ctrl.Result {Requeue : true }, err
219+ // Handle error during image import
220+ err = importImage (imageClient , image .ID , createOpts )
221+ if err != nil {
222+ // Handle error
223+ logger .Error (err , "Failed to import image" )
224+ return
225+ }
205226 }
206227 }
228+ // Check if image is active
229+ imageStatus , err = waitForImageActive (imageClient , imageID , 5 * time .Second , 3 * time .Minute )
230+ if err != nil {
231+ // Handle error
232+ logger .Error (err , "Failed to wait for image to become active" )
233+ return
234+ } else if imageStatus {
235+ logger .Info ("Image is active." )
236+ }
207237 }
208238
209- // Check if image is active
210- imageStatus , err = waitForImageActive (imageClient , imageID , 5 * time .Second , 10 * time .Minute )
211- if err != nil {
212- return ctrl.Result {Requeue : true }, fmt .Errorf ("Error waiting for image to become active: %w" , err )
213- } else if imageStatus {
214- logger .Info ("Image is active." )
239+ // Launch multiple goroutines to download images concurrently
240+ for i := 0 ; i < 1 ; i ++ { // Adjust the number based on desired concurrency, needs to be test it :)
241+ wg .Add (1 )
242+ go downloadImage ()
215243 }
216244
217- return ctrl.Result {}, nil
245+ // Wait for all goroutines to finish
246+ wg .Wait ()
247+
248+ return ctrl.Result {Requeue : true , RequeueAfter : 2 * time .Minute }, nil
218249}
219250
220251// SetupWithManager sets up the controller with the Manager.
0 commit comments