Skip to content
This repository was archived by the owner on Dec 16, 2025. It is now read-only.

Commit 7c6d831

Browse files
michal-gubrickymatofeder
authored andcommitted
Download images simultaneously
Signed-off-by: michal.gubricky <[email protected]>
1 parent 1afdfcd commit 7c6d831

File tree

1 file changed

+85
-54
lines changed

1 file changed

+85
-54
lines changed

internal/controller/openstacknodeimagerelease_controller.go

Lines changed: 85 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)