Skip to content

Commit 5ec0249

Browse files
authored
Merge pull request #527 from masnax/fixes
Fix concurrent access & cleanup timeout
2 parents 37e0126 + 0e1f9d8 commit 5ec0249

3 files changed

Lines changed: 43 additions & 12 deletions

File tree

cmd/migration-managerd/internal/api/workers.go

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -396,15 +396,13 @@ func (d *Daemon) beginImports(ctx context.Context, cleanupInstances bool) error
396396
// This is used so that we ensure each pool in each target is checked only once for volumes in a particular project, for a particular VM OS.
397397
visitedLocations := map[string]map[string]map[string]bool{}
398398
ignoredBatches := []string{}
399+
var volLock sync.Mutex
399400
err = util.RunConcurrentMap(migrationState, func(batchName string, state queue.MigrationState) error {
400401
log := log.With(slog.String("batch", state.Batch.Name))
401402
for instUUID, q := range state.QueueEntries {
402403
for _, pool := range q.Placement.StoragePools {
404+
volLock.Lock()
403405
// for every instance in this batch, check volumes at the corresponding target, unless we did already.
404-
if visitedLocations == nil {
405-
visitedLocations = map[string]map[string]map[string]bool{}
406-
}
407-
408406
if visitedLocations[q.Placement.TargetName] == nil {
409407
visitedLocations[q.Placement.TargetName] = map[string]map[string]bool{}
410408
}
@@ -413,18 +411,27 @@ func (d *Daemon) beginImports(ctx context.Context, cleanupInstances bool) error
413411
visitedLocations[q.Placement.TargetName][q.Placement.TargetProject] = map[string]bool{}
414412
}
415413

416-
if !visitedLocations[q.Placement.TargetName][q.Placement.TargetProject][pool] {
414+
shouldCreateVol := !visitedLocations[q.Placement.TargetName][q.Placement.TargetProject][pool]
415+
if shouldCreateVol {
416+
visitedLocations[q.Placement.TargetName][q.Placement.TargetProject][pool] = true
417+
}
418+
419+
volLock.Unlock()
420+
421+
if shouldCreateVol {
417422
err := d.ensureISOImagesExistInStoragePool(ctx, state.Instances[instUUID], state.Targets[instUUID], state.Batch, pool, q.Placement.TargetProject)
418423
if err != nil {
424+
volLock.Lock()
425+
visitedLocations[q.Placement.TargetName][q.Placement.TargetProject][pool] = false
426+
volLock.Unlock()
427+
419428
log.Error("Failed to validate batch", logger.Err(err))
420429
_, err := d.batch.UpdateStatusByName(ctx, state.Batch.Name, api.BATCHSTATUS_ERROR, err.Error())
421430
if err != nil {
422431
return fmt.Errorf("Failed to set batch status to %q: %w", api.BATCHSTATUS_ERROR, err)
423432
}
424433

425434
ignoredBatches = append(ignoredBatches, state.Batch.Name)
426-
} else {
427-
visitedLocations[q.Placement.TargetName][q.Placement.TargetProject][pool] = true
428435
}
429436
}
430437
}
@@ -672,7 +679,32 @@ func (d *Daemon) createTargetVM(ctx context.Context, b migration.Batch, inst mig
672679
if cleanupInstances {
673680
reverter.Add(func() {
674681
slog.Error("Cleaning up new instance after failure", slog.String("revert", "instance cleanup"), slog.Any("error", err))
675-
cleanup()
682+
683+
// Instantiate a new client.
684+
it, err := target.NewTarget(t.ToAPI())
685+
if err != nil {
686+
slog.Error("Failed to construct target", slog.String("name", t.Name), slog.Any("error", err))
687+
return
688+
}
689+
690+
timeoutCtx, cancel := context.WithTimeout(ctx, it.Timeout())
691+
defer cancel()
692+
693+
// Connect to the target.
694+
err = it.Connect(timeoutCtx)
695+
if err != nil {
696+
slog.Error("Failed to connect to target", slog.String("name", it.GetName()), slog.Any("error", err))
697+
return
698+
}
699+
700+
// Set the project.
701+
err = it.SetProject(q.Placement.TargetProject)
702+
if err != nil {
703+
slog.Error("Failed to set project", slog.String("project", q.Placement.TargetProject), slog.String("name", it.GetName()), slog.Any("error", err))
704+
return
705+
}
706+
707+
cleanup(it)
676708
})
677709
}
678710

internal/target/incus.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ func (t *InternalIncusTarget) CreateVMDefinition(instanceDef migration.Instance,
593593
return ret, nil
594594
}
595595

596-
func (t *InternalIncusTarget) CreateNewVM(ctx context.Context, instDef migration.Instance, apiDef incusAPI.InstancesPost, placement api.Placement, bootISOImage string) (func(context.Context) error, func(), error) {
596+
func (t *InternalIncusTarget) CreateNewVM(ctx context.Context, instDef migration.Instance, apiDef incusAPI.InstancesPost, placement api.Placement, bootISOImage string) (func(context.Context) error, func(t Target), error) {
597597
reverter := revert.New()
598598
defer reverter.Fail()
599599

@@ -618,7 +618,7 @@ func (t *InternalIncusTarget) CreateNewVM(ctx context.Context, instDef migration
618618
return nil, nil, err
619619
}
620620

621-
cleanup := func() {
621+
cleanup := func(t Target) {
622622
err := t.CleanupVM(context.Background(), apiDef.Name, true)
623623
if err != nil {
624624
slog.Error("Failed to clean up instance after error", slog.String("name", apiDef.Name), slog.Any("error", err))
@@ -678,7 +678,6 @@ func (t *InternalIncusTarget) SetupVM(ctx context.Context, instDef migration.Ins
678678
instInfo.Devices[diskKey]["source"] = diskName
679679
}
680680

681-
apiDef.Start = true
682681
op, err := tgtClient.UpdateInstance(instInfo.Name, instInfo.InstancePut, etag)
683682
if err != nil {
684683
return err

internal/target/interface.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ type Target interface {
8282
CreateVMDefinition(instanceDef migration.Instance, usedNetworks migration.Networks, q migration.QueueEntry, fingerprint string, endpoint string, targetNetwork api.MigrationNetworkPlacement) (incusAPI.InstancesPost, error)
8383

8484
// Creates a new VM from the pre-populated API definition.
85-
CreateNewVM(ctx context.Context, instDef migration.Instance, apiDef incusAPI.InstancesPost, placement api.Placement, bootISOImage string) (func(context.Context) error, func(), error)
85+
CreateNewVM(ctx context.Context, instDef migration.Instance, apiDef incusAPI.InstancesPost, placement api.Placement, bootISOImage string) (func(context.Context) error, func(t Target), error)
8686

8787
// Creates a new VM from the pre-populated API definition.
8888
SetupVM(ctx context.Context, instDef migration.Instance, apiDef incusAPI.InstancesPost, placement api.Placement) error

0 commit comments

Comments
 (0)