Skip to content

Commit

Permalink
Enhance provisioning speed and stability and Update test scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
cb-github-robot authored Oct 30, 2024
2 parents a98e5a4 + 4d1ac72 commit 43f1dc2
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 153 deletions.
60 changes: 46 additions & 14 deletions src/core/infra/provisioning.go
Original file line number Diff line number Diff line change
Expand Up @@ -957,30 +957,62 @@ func CreateMciDynamic(reqID string, nsId string, req *model.TbMciDynamicReq, dep
}

//If not, generate default resources dynamically.
// Parallel processing of VM requests
var wg sync.WaitGroup
var mutex sync.Mutex
errChan := make(chan error, len(vmRequest)) // Error channel to collect errors

for _, k := range vmRequest {
vmReq, err := getVmReqFromDynamicReq(reqID, nsId, &k)
wg.Add(1)

// Launch a goroutine for each VM request
go func(vmReq model.TbVmDynamicReq) {
defer wg.Done()

req, err := getVmReqFromDynamicReq(reqID, nsId, &vmReq)
if err != nil {
log.Error().Err(err).Msg("Failed to prepare resources for dynamic MCI creation")
errChan <- err
return
}

// Safely append to the shared mciReq.Vm slice
mutex.Lock()
mciReq.Vm = append(mciReq.Vm, *req)
mutex.Unlock()
}(k)
}

// Wait for all goroutines to complete
wg.Wait()
close(errChan) // Close the error channel after processing

// Check for any errors from the goroutines
for err := range errChan {
if err != nil {
log.Error().Err(err).Msg("Failed to prefare resources for dynamic MCI creation")
// Rollback created default resources
// Rollback if any error occurs
log.Info().Msg("Rolling back created default resources")
time.Sleep(5 * time.Second)
log.Info().Msg("Try rollback created default resources")
rollbackResult, rollbackErr := resource.DelAllSharedResources(nsId)
if rollbackErr != nil {
err = fmt.Errorf("Failed in rollback operation: %w", rollbackErr)
if rollbackResult, rollbackErr := resource.DelAllSharedResources(nsId); rollbackErr != nil {
return emptyMci, fmt.Errorf("failed in rollback operation: %w", rollbackErr)
} else {
ids := strings.Join(rollbackResult.IdList, ", ")
err = fmt.Errorf("Rollback results [%s]: %w", ids, err)
return emptyMci, fmt.Errorf("rollback results [%s]: %w", ids, err)
}
return emptyMci, err
}
mciReq.Vm = append(mciReq.Vm, *vmReq)
}

// Log the prepared MCI request and update the progress
common.PrintJsonPretty(mciReq)
common.UpdateRequestProgress(reqID, common.ProgressInfo{Title: "Prepared all resources for provisioning MCI:" + mciReq.Name, Info: mciReq, Time: time.Now()})
common.UpdateRequestProgress(reqID, common.ProgressInfo{Title: "Start provisioning", Time: time.Now()})

// Run create MCI with the generated MCI request (option != register)
common.UpdateRequestProgress(reqID, common.ProgressInfo{
Title: "Prepared all resources for provisioning MCI: " + mciReq.Name,
Info: mciReq, Time: time.Now(),
})
common.UpdateRequestProgress(reqID, common.ProgressInfo{
Title: "Start instance provisioning", Time: time.Now(),
})

// Run create MCI with the generated MCI request
option := "create"
if deployOption == "hold" {
option = "hold"
Expand Down
50 changes: 41 additions & 9 deletions src/core/resource/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ func init() {
validate.RegisterStructValidation(TbVNetReqStructLevelValidation, model.TbVNetReq{})
}

// DelAllResources deletes all TB Resource object of given resourceType
// DelAllResources deletes all TB Resource objects of the given resourceType.
func DelAllResources(nsId string, resourceType string, subString string, forceFlag string) (model.IdList, error) {

deletedResources := model.IdList{}
deleteStatus := ""
var mutex sync.Mutex // Protect shared slice access
var wg sync.WaitGroup // Synchronize all goroutines

err := common.CheckString(nsId)
if err != nil {
Expand All @@ -89,27 +89,59 @@ func DelAllResources(nsId string, resourceType string, subString string, forceFl
}

if len(resourceIdList) == 0 {
errString := "There is no " + resourceType + " resource in " + nsId
errString := fmt.Sprintf("There is no %s resource in %s", resourceType, nsId)
err := fmt.Errorf(errString)
log.Error().Err(err).Msg("")
return deletedResources, err
}

// Channel to capture errors
errChan := make(chan error, len(resourceIdList))

// Process each resourceId concurrently
for _, v := range resourceIdList {
// if subString is provided, check the resourceId contains the subString.
if subString == "" || strings.Contains(v, subString) {
// Increment WaitGroup counter
wg.Add(1)

// Launch a goroutine for each resource deletion
go func(resourceId string) {
defer wg.Done()
common.RandomSleep(0, len(resourceIdList)/10)

// Check if the resourceId matches the subString criteria
if subString != "" && !strings.Contains(resourceId, subString) {
return
}

deleteStatus = "[Done] "
// Attempt to delete the resource
deleteStatus := "[Done] "
errString := ""

err := DelResource(nsId, resourceType, v, forceFlag)
err := DelResource(nsId, resourceType, resourceId, forceFlag)
if err != nil {
deleteStatus = "[Failed] "
errString = " (" + err.Error() + ")"
errChan <- err // Send error to the error channel
}
deletedResources.IdList = append(deletedResources.IdList, deleteStatus+resourceType+": "+v+errString)

// Safely append the result to deletedResources.IdList using mutex
mutex.Lock()
deletedResources.IdList = append(deletedResources.IdList, deleteStatus+resourceType+": "+resourceId+errString)
mutex.Unlock()
}(v) // Pass loop variable as an argument to avoid race conditions
}

// Wait for all goroutines to complete
wg.Wait()
close(errChan) // Close the error channel

// Collect any errors from the error channel
for err := range errChan {
if err != nil {
log.Info().Err(err).Msg("error deleting resource")
}
}

return deletedResources, nil
}

Expand Down
Loading

0 comments on commit 43f1dc2

Please sign in to comment.