Skip to content

Commit 6553e22

Browse files
authored
Merge pull request #1842 from stgraber/main
Standalone changes from the Linstor branch
2 parents 9d755fd + 45ef3b4 commit 6553e22

18 files changed

+104
-35
lines changed

cmd/incusd/migrate_storage_volumes.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ func (s *migrationSourceWs) DoStorage(state *state.State, projectName string, po
138138
// to false here. The migration source/sender doesn't need to care whether
139139
// or not it's doing a refresh as the migration sink/receiver will know
140140
// this, and adjust the migration types accordingly.
141-
poolMigrationTypes = pool.MigrationTypes(storageDrivers.ContentType(srcConfig.Volume.ContentType), false, !s.volumeOnly)
141+
// The same applies for clusterMove and storageMove, which are set to the most optimized defaults.
142+
poolMigrationTypes = pool.MigrationTypes(storageDrivers.ContentType(srcConfig.Volume.ContentType), false, !s.volumeOnly, true, false)
142143
if len(poolMigrationTypes) == 0 {
143144
return fmt.Errorf("No source migration types available")
144145
}
@@ -338,10 +339,12 @@ func (c *migrationSink) DoStorage(state *state.State, projectName string, poolNa
338339
// Refresh needs to be set.
339340
offerHeader.Refresh = &c.refresh
340341

342+
clusterMove := req.Source.Location != ""
343+
341344
// Extract the source's migration type and then match it against our pool's
342345
// supported types and features. If a match is found the combined features list
343346
// will be sent back to requester.
344-
respTypes, err := localMigration.MatchTypes(offerHeader, storagePools.FallbackMigrationType(contentType), pool.MigrationTypes(contentType, c.refresh, !c.volumeOnly))
347+
respTypes, err := localMigration.MatchTypes(offerHeader, storagePools.FallbackMigrationType(contentType), pool.MigrationTypes(contentType, c.refresh, !c.volumeOnly, clusterMove, poolName != "" && req.Source.Pool != poolName || !clusterMove))
345348
if err != nil {
346349
return err
347350
}

internal/server/instance/drivers/driver_lxc.go

+13-4
Original file line numberDiff line numberDiff line change
@@ -5502,10 +5502,14 @@ func (d *lxc) MigrateSend(args instance.MigrateSendArgs) error {
55025502
return err
55035503
}
55045504

5505+
clusterMove := args.ClusterMoveSourceName != ""
5506+
storageMove := args.StoragePool != ""
5507+
55055508
// The refresh argument passed to MigrationTypes() is always set to false here.
55065509
// The migration source/sender doesn't need to care whether or not it's doing a refresh as the migration
55075510
// sink/receiver will know this, and adjust the migration types accordingly.
5508-
poolMigrationTypes := pool.MigrationTypes(storagePools.InstanceContentType(d), false, args.Snapshots)
5511+
// The same applies for clusterMove and storageMove, which are set to the most optimized defaults.
5512+
poolMigrationTypes := pool.MigrationTypes(storagePools.InstanceContentType(d), false, args.Snapshots, true, false)
55095513
if len(poolMigrationTypes) == 0 {
55105514
err := fmt.Errorf("No source migration types available")
55115515
op.Done(err)
@@ -5614,7 +5618,8 @@ func (d *lxc) MigrateSend(args instance.MigrateSendArgs) error {
56145618
AllowInconsistent: args.AllowInconsistent,
56155619
VolumeOnly: !args.Snapshots,
56165620
Info: &localMigration.Info{Config: srcConfig},
5617-
ClusterMove: args.ClusterMoveSourceName != "",
5621+
ClusterMove: clusterMove,
5622+
StorageMove: storageMove,
56185623
}
56195624

56205625
// Only send the snapshots that the target requests when refreshing.
@@ -6151,10 +6156,13 @@ func (d *lxc) MigrateReceive(args instance.MigrateReceiveArgs) error {
61516156
// However, to determine the correct migration type Refresh needs to be set.
61526157
offerHeader.Refresh = &args.Refresh
61536158

6159+
clusterMove := args.ClusterMoveSourceName != ""
6160+
storageMove := args.StoragePool != ""
6161+
61546162
// Extract the source's migration type and then match it against our pool's supported types and features.
61556163
// If a match is found the combined features list will be sent back to requester.
61566164
contentType := storagePools.InstanceContentType(d)
6157-
respTypes, err := localMigration.MatchTypes(offerHeader, storagePools.FallbackMigrationType(contentType), pool.MigrationTypes(contentType, args.Refresh, args.Snapshots))
6165+
respTypes, err := localMigration.MatchTypes(offerHeader, storagePools.FallbackMigrationType(contentType), pool.MigrationTypes(contentType, args.Refresh, args.Snapshots, clusterMove, storageMove))
61586166
if err != nil {
61596167
return err
61606168
}
@@ -6378,6 +6386,7 @@ func (d *lxc) MigrateReceive(args instance.MigrateReceiveArgs) error {
63786386
VolumeSize: offerHeader.GetVolumeSize(), // Block size setting override.
63796387
VolumeOnly: !args.Snapshots,
63806388
ClusterMoveSourceName: args.ClusterMoveSourceName,
6389+
StoragePool: args.StoragePool,
63816390
}
63826391

63836392
// At this point we have already figured out the parent container's root
@@ -6436,7 +6445,7 @@ func (d *lxc) MigrateReceive(args instance.MigrateReceiveArgs) error {
64366445
return fmt.Errorf("Failed creating instance on target: %w", err)
64376446
}
64386447

6439-
isRemoteClusterMove := args.ClusterMoveSourceName != "" && pool.Driver().Info().Remote
6448+
isRemoteClusterMove := clusterMove && pool.Driver().Info().Remote
64406449

64416450
// Only delete all instance volumes on error if the pool volume creation has succeeded to
64426451
// avoid deleting an existing conflicting volume.

internal/server/instance/drivers/driver_qemu.go

+12-5
Original file line numberDiff line numberDiff line change
@@ -6702,11 +6702,15 @@ func (d *qemu) MigrateSend(args instance.MigrateSendArgs) error {
67026702
return err
67036703
}
67046704

6705+
clusterMove := args.ClusterMoveSourceName != ""
6706+
storageMove := args.StoragePool != ""
6707+
67056708
// The refresh argument passed to MigrationTypes() is always set
67066709
// to false here. The migration source/sender doesn't need to care whether
67076710
// or not it's doing a refresh as the migration sink/receiver will know
67086711
// this, and adjust the migration types accordingly.
6709-
poolMigrationTypes := pool.MigrationTypes(storagePools.InstanceContentType(d), false, args.Snapshots)
6712+
// The same applies for clusterMove and storageMove, which are set to the most optimized defaults.
6713+
poolMigrationTypes := pool.MigrationTypes(storagePools.InstanceContentType(d), false, args.Snapshots, true, false)
67106714
if len(poolMigrationTypes) == 0 {
67116715
err := fmt.Errorf("No source migration types available")
67126716
op.Done(err)
@@ -6804,8 +6808,8 @@ func (d *qemu) MigrateSend(args instance.MigrateSendArgs) error {
68046808
AllowInconsistent: args.AllowInconsistent,
68056809
VolumeOnly: !args.Snapshots,
68066810
Info: &localMigration.Info{Config: srcConfig},
6807-
ClusterMove: args.ClusterMoveSourceName != "",
6808-
StorageMove: args.StoragePool != "",
6811+
ClusterMove: clusterMove,
6812+
StorageMove: storageMove,
68096813
}
68106814

68116815
// Only send the snapshots that the target requests when refreshing.
@@ -7345,10 +7349,13 @@ func (d *qemu) MigrateReceive(args instance.MigrateReceiveArgs) error {
73457349
// However, to determine the correct migration type Refresh needs to be set.
73467350
offerHeader.Refresh = &args.Refresh
73477351

7352+
clusterMove := args.ClusterMoveSourceName != ""
7353+
storageMove := args.StoragePool != ""
7354+
73487355
// Extract the source's migration type and then match it against our pool's supported types and features.
73497356
// If a match is found the combined features list will be sent back to requester.
73507357
contentType := storagePools.InstanceContentType(d)
7351-
respTypes, err := localMigration.MatchTypes(offerHeader, storagePools.FallbackMigrationType(contentType), pool.MigrationTypes(contentType, args.Refresh, args.Snapshots))
7358+
respTypes, err := localMigration.MatchTypes(offerHeader, storagePools.FallbackMigrationType(contentType), pool.MigrationTypes(contentType, args.Refresh, args.Snapshots, clusterMove, storageMove))
73527359
if err != nil {
73537360
return err
73547361
}
@@ -7657,7 +7664,7 @@ func (d *qemu) MigrateReceive(args instance.MigrateReceiveArgs) error {
76577664

76587665
// Only delete all instance volumes on error if the pool volume creation has succeeded to
76597666
// avoid deleting an existing conflicting volume.
7660-
isRemoteClusterMove := args.ClusterMoveSourceName != "" && poolInfo.Remote
7667+
isRemoteClusterMove := clusterMove && poolInfo.Remote
76617668
if !volTargetArgs.Refresh && !isRemoteClusterMove {
76627669
revert.Add(func() {
76637670
snapshots, _ := d.Snapshots()

internal/server/storage/backend.go

+23-14
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,13 @@ func (b *backend) Driver() drivers.Driver {
165165
return b.driver
166166
}
167167

168-
// MigrationTypes returns the migration transport method preferred when sending a migration,
169-
// based on the migration method requested by the driver's ability. The snapshots argument
170-
// indicates whether snapshots are migrated as well. It is used to determine whether to use
171-
// optimized migration.
172-
func (b *backend) MigrationTypes(contentType drivers.ContentType, refresh bool, copySnapshots bool) []localMigration.Type {
173-
return b.driver.MigrationTypes(contentType, refresh, copySnapshots)
168+
// MigrationTypes returns the migration transport method preferred when sending a migration, based
169+
// on the migration method requested by the driver's ability. The copySnapshots argument indicates
170+
// whether snapshots are migrated as well. clusterMove determines whether the migration is done
171+
// within a cluster and storageMove determines whether the storage pool is changed by the migration.
172+
// This method is used to determine whether to use optimized migration.
173+
func (b *backend) MigrationTypes(contentType drivers.ContentType, refresh bool, copySnapshots bool, clusterMove bool, storageMove bool) []localMigration.Type {
174+
return b.driver.MigrationTypes(contentType, refresh, copySnapshots, clusterMove, storageMove)
174175
}
175176

176177
// Create creates the storage pool layout on the storage device.
@@ -1150,9 +1151,9 @@ func (b *backend) CreateInstanceFromCopy(inst instance.Instance, src instance.In
11501151
l.Debug("CreateInstanceFromCopy cross-pool mode detected")
11511152

11521153
// Negotiate the migration type to use.
1153-
offeredTypes := srcPool.MigrationTypes(contentType, false, snapshots)
1154+
offeredTypes := srcPool.MigrationTypes(contentType, false, snapshots, false, true)
11541155
offerHeader := localMigration.TypesToHeader(offeredTypes...)
1155-
migrationTypes, err := localMigration.MatchTypes(offerHeader, FallbackMigrationType(contentType), b.MigrationTypes(contentType, false, snapshots))
1156+
migrationTypes, err := localMigration.MatchTypes(offerHeader, FallbackMigrationType(contentType), b.MigrationTypes(contentType, false, snapshots, false, true))
11561157
if err != nil {
11571158
return fmt.Errorf("Failed to negotiate copy migration type: %w", err)
11581159
}
@@ -1196,6 +1197,7 @@ func (b *backend) CreateInstanceFromCopy(inst instance.Instance, src instance.In
11961197
AllowInconsistent: allowInconsistent,
11971198
VolumeOnly: !snapshots,
11981199
Info: &localMigration.Info{Config: srcConfig},
1200+
StorageMove: true,
11991201
}, op)
12001202
})
12011203

@@ -1208,6 +1210,7 @@ func (b *backend) CreateInstanceFromCopy(inst instance.Instance, src instance.In
12081210
VolumeSize: srcVolumeSize, // Block size setting override.
12091211
TrackProgress: false, // Do not use a progress tracker on receiver.
12101212
VolumeOnly: !snapshots,
1213+
StoragePool: srcPool.Name(),
12111214
}, op)
12121215
})
12131216

@@ -1398,9 +1401,9 @@ func (b *backend) RefreshCustomVolume(projectName string, srcProjectName string,
13981401
l.Debug("RefreshCustomVolume cross-pool mode detected")
13991402

14001403
// Negotiate the migration type to use.
1401-
offeredTypes := srcPool.MigrationTypes(contentType, true, snapshots)
1404+
offeredTypes := srcPool.MigrationTypes(contentType, true, snapshots, false, true)
14021405
offerHeader := localMigration.TypesToHeader(offeredTypes...)
1403-
migrationTypes, err := localMigration.MatchTypes(offerHeader, FallbackMigrationType(contentType), b.MigrationTypes(contentType, true, snapshots))
1406+
migrationTypes, err := localMigration.MatchTypes(offerHeader, FallbackMigrationType(contentType), b.MigrationTypes(contentType, true, snapshots, false, true))
14041407
if err != nil {
14051408
return fmt.Errorf("Failed to negotiate copy migration type: %w", err)
14061409
}
@@ -1456,6 +1459,7 @@ func (b *backend) RefreshCustomVolume(projectName string, srcProjectName string,
14561459
TrackProgress: true, // Do use a progress tracker on sender.
14571460
ContentType: string(contentType),
14581461
Info: &localMigration.Info{Config: srcConfig},
1462+
StorageMove: true,
14591463
}, op)
14601464
if err != nil {
14611465
cancel()
@@ -1476,6 +1480,7 @@ func (b *backend) RefreshCustomVolume(projectName string, srcProjectName string,
14761480
ContentType: string(contentType),
14771481
VolumeSize: volSize, // Block size setting override.
14781482
Refresh: true,
1483+
StoragePool: srcPoolName,
14791484
}, op)
14801485
if err != nil {
14811486
cancel()
@@ -1643,9 +1648,9 @@ func (b *backend) RefreshInstance(inst instance.Instance, src instance.Instance,
16431648
l.Debug("RefreshInstance cross-pool mode detected")
16441649

16451650
// Negotiate the migration type to use.
1646-
offeredTypes := srcPool.MigrationTypes(contentType, true, snapshots)
1651+
offeredTypes := srcPool.MigrationTypes(contentType, true, snapshots, false, true)
16471652
offerHeader := localMigration.TypesToHeader(offeredTypes...)
1648-
migrationTypes, err := localMigration.MatchTypes(offerHeader, FallbackMigrationType(contentType), b.MigrationTypes(contentType, true, snapshots))
1653+
migrationTypes, err := localMigration.MatchTypes(offerHeader, FallbackMigrationType(contentType), b.MigrationTypes(contentType, true, snapshots, false, true))
16491654
if err != nil {
16501655
return fmt.Errorf("Failed to negotiate copy migration type: %w", err)
16511656
}
@@ -1686,6 +1691,7 @@ func (b *backend) RefreshInstance(inst instance.Instance, src instance.Instance,
16861691
Refresh: true, // Indicate to sender to use incremental streams.
16871692
Info: &localMigration.Info{Config: srcConfig},
16881693
VolumeOnly: !snapshots,
1694+
StorageMove: true,
16891695
}, op)
16901696
})
16911697

@@ -1699,6 +1705,7 @@ func (b *backend) RefreshInstance(inst instance.Instance, src instance.Instance,
16991705
VolumeSize: srcVolumeSize,
17001706
TrackProgress: false, // Do not use a progress tracker on receiver.
17011707
VolumeOnly: !snapshots,
1708+
StoragePool: srcPool.Name(),
17021709
}, op)
17031710
})
17041711

@@ -4812,9 +4819,9 @@ func (b *backend) CreateCustomVolumeFromCopy(projectName string, srcProjectName
48124819
l.Debug("CreateCustomVolumeFromCopy cross-pool mode detected")
48134820

48144821
// Negotiate the migration type to use.
4815-
offeredTypes := srcPool.MigrationTypes(contentType, false, snapshots)
4822+
offeredTypes := srcPool.MigrationTypes(contentType, false, snapshots, false, true)
48164823
offerHeader := localMigration.TypesToHeader(offeredTypes...)
4817-
migrationTypes, err := localMigration.MatchTypes(offerHeader, FallbackMigrationType(contentType), b.MigrationTypes(contentType, false, snapshots))
4824+
migrationTypes, err := localMigration.MatchTypes(offerHeader, FallbackMigrationType(contentType), b.MigrationTypes(contentType, false, snapshots, false, true))
48184825
if err != nil {
48194826
return fmt.Errorf("Failed to negotiate copy migration type: %w", err)
48204827
}
@@ -4874,6 +4881,7 @@ func (b *backend) CreateCustomVolumeFromCopy(projectName string, srcProjectName
48744881
ContentType: string(contentType),
48754882
Info: &localMigration.Info{Config: srcConfig},
48764883
VolumeOnly: !snapshots,
4884+
StorageMove: true,
48774885
}, op)
48784886
if err != nil {
48794887
cancel()
@@ -4894,6 +4902,7 @@ func (b *backend) CreateCustomVolumeFromCopy(projectName string, srcProjectName
48944902
ContentType: string(contentType),
48954903
VolumeSize: volSize, // Block size setting override.
48964904
VolumeOnly: !snapshots,
4905+
StoragePool: srcPool.Name(),
48974906
}, op)
48984907
if err != nil {
48994908
cancel()

internal/server/storage/backend_mock.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ func (b *mockBackend) Driver() drivers.Driver {
6363
return b.driver
6464
}
6565

66-
func (b *mockBackend) MigrationTypes(contentType drivers.ContentType, refresh bool, copySnapshots bool) []migration.Type {
66+
// MigrationTypes returns the type of transfer methods to be used when doing migrations between pools in preference order.
67+
func (b *mockBackend) MigrationTypes(contentType drivers.ContentType, refresh bool, copySnapshots bool, clusterMove bool, storageMove bool) []migration.Type {
6768
return []migration.Type{
6869
{
6970
FSType: FallbackMigrationType(contentType),

internal/server/storage/drivers/driver_btrfs.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ func (d *btrfs) GetResources() (*api.ResourcesStoragePool, error) {
488488
}
489489

490490
// MigrationType returns the type of transfer methods to be used when doing migrations between pools in preference order.
491-
func (d *btrfs) MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool) []localMigration.Type {
491+
func (d *btrfs) MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool, clusterMove bool, storageMove bool) []localMigration.Type {
492492
var rsyncFeatures []string
493493
btrfsFeatures := []string{migration.BTRFSFeatureMigrationHeader, migration.BTRFSFeatureSubvolumes, migration.BTRFSFeatureSubvolumeUUIDs}
494494

internal/server/storage/drivers/driver_ceph.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ func (d *ceph) GetResources() (*api.ResourcesStoragePool, error) {
394394
}
395395

396396
// MigrationType returns the type of transfer methods to be used when doing migrations between pools in preference order.
397-
func (d *ceph) MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool) []localMigration.Type {
397+
func (d *ceph) MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool, clusterMove bool, storageMove bool) []localMigration.Type {
398398
var rsyncFeatures []string
399399

400400
// Do not pass compression argument to rsync if the associated

internal/server/storage/drivers/driver_cephfs.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ func (d *cephfs) GetResources() (*api.ResourcesStoragePool, error) {
482482
}
483483

484484
// MigrationTypes returns the supported migration types and options supported by the driver.
485-
func (d *cephfs) MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool) []localMigration.Type {
485+
func (d *cephfs) MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool, clusterMove bool, storageMove bool) []localMigration.Type {
486486
var rsyncFeatures []string
487487

488488
// Do not pass compression argument to rsync if the associated

internal/server/storage/drivers/driver_cephobject.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,6 @@ func (d *cephobject) GetResources() (*api.ResourcesStoragePool, error) {
201201
}
202202

203203
// MigrationTypes returns the supported migration types and options supported by the driver.
204-
func (d *cephobject) MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool) []migration.Type {
204+
func (d *cephobject) MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool, clusterMove bool, storageMove bool) []migration.Type {
205205
return nil
206206
}

internal/server/storage/drivers/driver_common.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ func (d *common) validateVolume(vol Volume, driverRules map[string]func(value st
202202

203203
// MigrationType returns the type of transfer methods to be used when doing migrations between pools
204204
// in preference order.
205-
func (d *common) MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool) []localMigration.Type {
205+
func (d *common) MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool, clusterMove bool, storageMove bool) []localMigration.Type {
206206
var transportType migration.MigrationFSType
207207
var rsyncFeatures []string
208208

internal/server/storage/drivers/driver_zfs.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ func (d *zfs) GetResources() (*api.ResourcesStoragePool, error) {
672672
}
673673

674674
// MigrationType returns the type of transfer methods to be used when doing migrations between pools in preference order.
675-
func (d *zfs) MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool) []localMigration.Type {
675+
func (d *zfs) MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool, clusterMove bool, storageMove bool) []localMigration.Type {
676676
var rsyncFeatures []string
677677

678678
// Do not pass compression argument to rsync if the associated

internal/server/storage/drivers/interface.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ type Driver interface {
102102
RestoreVolume(vol Volume, snapshotName string, op *operations.Operation) error
103103

104104
// Migration.
105-
MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool) []migration.Type
105+
MigrationTypes(contentType ContentType, refresh bool, copySnapshots bool, clusterMove bool, storageMove bool) []migration.Type
106106
MigrateVolume(vol Volume, conn io.ReadWriteCloser, volSrcArgs *migration.VolumeSourceArgs, op *operations.Operation) error
107107
CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, volTargetArgs migration.VolumeTargetArgs, preFiller *VolumeFiller, op *operations.Operation) error
108108

internal/server/storage/pool_interface.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ type Pool interface {
138138
RestoreCustomVolume(projectName string, volName string, snapshotName string, op *operations.Operation) error
139139

140140
// Custom volume migration.
141-
MigrationTypes(contentType drivers.ContentType, refresh bool, copySnapshots bool) []migration.Type
141+
MigrationTypes(contentType drivers.ContentType, refresh bool, copySnapshots bool, clusterMove bool, storageMove bool) []migration.Type
142142
CreateCustomVolumeFromMigration(projectName string, conn io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) error
143143
MigrateCustomVolume(projectName string, conn io.ReadWriteCloser, args *migration.VolumeSourceArgs, op *operations.Operation) error
144144

0 commit comments

Comments
 (0)