[lxc-devel] [lxd/master] Storage Volume Copy using in-memory pipe and migration logic
tomponline on Github
lxc-bot at linuxcontainers.org
Wed Oct 30 13:39:29 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 543 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191030/8ed57ea5/attachment.bin>
-------------- next part --------------
From 19100009dea691fa57b8fa0e24f6db522e82c7df Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 30 Oct 2019 13:28:27 +0000
Subject: [PATCH 1/9] lxd/storage/memorypipe: Adds in-memory bidirectional pipe
Compatible with the io.ReadWriteCloser interface.
Used for simulating WebsocketIO between local endpoints.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/memorypipe/memory_pipe.go | 72 +++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
create mode 100644 lxd/storage/memorypipe/memory_pipe.go
diff --git a/lxd/storage/memorypipe/memory_pipe.go b/lxd/storage/memorypipe/memory_pipe.go
new file mode 100644
index 0000000000..2484c30c3b
--- /dev/null
+++ b/lxd/storage/memorypipe/memory_pipe.go
@@ -0,0 +1,72 @@
+package memorypipe
+
+import (
+ "io"
+)
+
+// msg represents an internal structure sent between the pipes.
+type msg struct {
+ data []byte
+ err error
+}
+
+// pipe provides a bidirectional pipe compatible with io.ReadWriteCloser interface.
+// Note, however, that it does not behave exactly how one would expect an io.ReadWriteCloser to
+// behave. Specifically the Close() function does not close the pipe, but instead delivers an io.EOF
+// error to the next reader. After which it can be read again to receive new data. This means the
+// pipe can be closed multiple times. Each time it indicates that one particular session has ended.
+// The reason for this is to emulate the WebsocketIO's behaviour by allowing a single persistent
+// connection to be used for multiple sessions.
+type pipe struct {
+ ch chan msg
+ otherEnd *pipe
+}
+
+// Read reads from the pipe into p. Returns number of bytes read and any errors.
+func (p *pipe) Read(b []byte) (int, error) {
+ msg := <-p.ch
+ if msg.err == io.EOF {
+ return -1, msg.err
+ }
+ n := copy(b, msg.data)
+ return n, msg.err
+}
+
+// Write writes to the pipe from p. Returns number of bytes written and any errors.
+func (p *pipe) Write(b []byte) (int, error) {
+ msg := msg{
+ data: append(b[:0:0], b...), // Create copy of b in case it is modified externally.
+ err: nil,
+ }
+ p.otherEnd.ch <- msg // Send msg to the other side's Read function.
+ return len(msg.data), msg.err
+}
+
+// Close is unusual in that it doesn't actually close the pipe. Instead it sends an io.EOF error
+// to the other side's Read function. This is so the other side can detect that a session has ended.
+// Each call to Close will indicate to the other side that a session has ended, whilst allowing the
+// reuse of a single persistent pipe for multiple sessions.
+func (p *pipe) Close() error {
+ p.otherEnd.ch <- msg{
+ data: nil,
+ err: io.EOF, // Indicates to the other side's Read function that session has ended.
+ }
+ return nil
+}
+
+// NewPipePair returns a pair of io.ReadWriterCloser pipes that are connected together such that
+// writes to one will appear as reads on the other and vice versa. Calling Close() on one end will
+// indicate to the other end that the session has ended.
+func NewPipePair() (io.ReadWriteCloser, io.ReadWriteCloser) {
+ aEnd := &pipe{
+ ch: make(chan msg, 1),
+ }
+
+ bEnd := &pipe{
+ ch: make(chan msg, 1),
+ }
+
+ aEnd.otherEnd = bEnd
+ bEnd.otherEnd = aEnd
+ return aEnd, bEnd
+}
From 126de79bafff4e082cac3b078e674d0fc3dad7c9 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 30 Oct 2019 13:29:16 +0000
Subject: [PATCH 2/9] lxd/migrate/storage/volumes: Updates use of migrate
functions
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/migrate_storage_volumes.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/migrate_storage_volumes.go b/lxd/migrate_storage_volumes.go
index ce232d9f65..a60ea178ba 100644
--- a/lxd/migrate_storage_volumes.go
+++ b/lxd/migrate_storage_volumes.go
@@ -156,7 +156,7 @@ func (s *migrationSourceWs) DoStorage(state *state.State, poolName string, volNa
Snapshots: snapshotNames,
}
- err = pool.MigrateCustomVolume(&shared.WebsocketIO{Conn: s.fsConn}, volSourceArgs, migrateOp)
+ err = pool.MigrateCustomVolume(&shared.WebsocketIO{Conn: s.fsConn}, volSourceArgs, true, migrateOp)
if err != nil {
go s.sendControl(err)
return err
@@ -371,7 +371,7 @@ func (c *migrationSink) DoStorage(state *state.State, poolName string, req *api.
}
}
- return pool.CreateCustomVolumeFromMigration(&shared.WebsocketIO{Conn: conn}, volTargetArgs, op)
+ return pool.CreateCustomVolumeFromMigration(&shared.WebsocketIO{Conn: conn}, volTargetArgs, true, op)
}
} else {
// Setup legacy storage migration sink if destination pool isn't supported yet by
From b4b678d07c379741d0a9ee89ff301b38923a6a49 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 30 Oct 2019 13:31:24 +0000
Subject: [PATCH 3/9] lxd/storage/backend/lxd: Updates
CreateCustomVolumeFromCopy to use migration logic
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/backend_lxd.go | 99 ++++++++++++++++++++------------------
1 file changed, 53 insertions(+), 46 deletions(-)
diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 277c2b1f4f..368f7f5173 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -11,6 +11,7 @@ import (
"github.com/lxc/lxd/lxd/operations"
"github.com/lxc/lxd/lxd/state"
"github.com/lxc/lxd/lxd/storage/drivers"
+ "github.com/lxc/lxd/lxd/storage/memorypipe"
"github.com/lxc/lxd/shared"
"github.com/lxc/lxd/shared/api"
)
@@ -273,12 +274,6 @@ func (b *lxdBackend) CreateCustomVolume(volName, desc string, config map[string]
// CreateCustomVolumeFromCopy creates a custom volume from an existing custom volume.
// It copies the snapshots from the source volume by default, but can be disabled if requested.
func (b *lxdBackend) CreateCustomVolumeFromCopy(volName, desc string, config map[string]string, srcPoolName, srcVolName string, srcVolOnly bool, op *operations.Operation) error {
- // Default to copying snapshots too, but if VolumeOnly is supplied then we only copy volume.
- copySnapshots := true
- if srcVolOnly {
- copySnapshots = false
- }
-
// Setup the source pool backend instance.
var srcPool *lxdBackend
if b.name == srcPoolName {
@@ -319,60 +314,72 @@ func (b *lxdBackend) CreateCustomVolumeFromCopy(volName, desc string, config map
desc = srcVolRow.Description
}
- // Check the supplied config and remove any fields not relevant for destination pool type.
- err = b.driver.ValidateVolume(config, true)
- if err != nil {
- return err
- }
+ // If we are copying snapshots, retrieve a list of snapshots from source volume.
+ snapshotNames := []string{}
+ if !srcVolOnly {
+ snapshots, err := VolumeSnapshotsGet(b.state, srcPoolName, srcVolName, db.StoragePoolVolumeTypeCustom)
+ if err != nil {
+ return err
+ }
- // Create slice to record DB volumes created if revert needed later.
- revertDBVolumes := []string{}
- defer func() {
- // Remove any DB volume rows created if we are reverting.
- for _, volName := range revertDBVolumes {
- b.state.Cluster.StoragePoolVolumeDelete("default", volName, db.StoragePoolVolumeTypeCustom, b.ID())
+ for _, snapshot := range snapshots {
+ _, snapShotName, _ := shared.ContainerGetParentAndSnapshotName(snapshot.Name)
+ snapshotNames = append(snapshotNames, snapShotName)
}
- }()
+ }
- // Create database entry for new storage volume.
- err = VolumeDBCreate(b.state, b.name, volName, desc, db.StoragePoolVolumeTypeNameCustom, false, config)
+ // Create in-memory pipe pair to simulate a connection between the sender and receiver.
+ aEnd, bEnd := memorypipe.NewPipePair()
+
+ // Negotiate the migration type to use.
+ offeredTypes := srcPool.MigrationTypes(drivers.ContentTypeFS)
+ offerHeader := migration.TypesToHeader(offeredTypes...)
+ migrationType, err := migration.MatchTypes(offerHeader, b.MigrationTypes(drivers.ContentTypeFS))
if err != nil {
- return err
+ return fmt.Errorf("Failed to neogotiate copy migration type: %v", err)
}
- revertDBVolumes = append(revertDBVolumes, volName)
+ // Run sender and receiver in separate go routines to prevent deadlocks.
+ aEndErrCh := make(chan error, 1)
+ bEndErrCh := make(chan error, 1)
+ go func() {
+ err := srcPool.MigrateCustomVolume(aEnd, migration.VolumeSourceArgs{
+ Name: srcVolName,
+ Snapshots: snapshotNames,
+ MigrationType: migrationType,
+ }, false, op) // Do not use a progress tracker on sender.
- if copySnapshots {
- // If we are copying snapshots, retrieve a list of snapshots from source volume.
- snapshots, err := VolumeSnapshotsGet(b.state, srcPoolName, volName, db.StoragePoolVolumeTypeCustom)
- if err != nil {
- return err
- }
+ aEndErrCh <- err
+ }()
- // Create a database entry and copy the volume for each snapshot.
- for _, srcSnapshot := range snapshots {
- // Convert the source snapshot volume name into the new snapshot volume name.
- _, snapName, _ := shared.ContainerGetParentAndSnapshotName(srcSnapshot.Name)
- newSnapshotName := drivers.GetSnapshotVolumeName(volName, snapName)
+ go func() {
+ err := b.CreateCustomVolumeFromMigration(bEnd, migration.VolumeTargetArgs{
+ Name: volName,
+ Description: desc,
+ Config: config,
+ Snapshots: snapshotNames,
+ MigrationType: migrationType,
+ }, true, op) // Do use a progress tracker on receiver.
- // Create database entry for new storage volume.
- err = VolumeDBCreate(b.state, b.name, newSnapshotName, srcSnapshot.Description, db.StoragePoolVolumeTypeNameCustom, true, config)
- if err != nil {
- return err
- }
+ bEndErrCh <- err
+ }()
- revertDBVolumes = append(revertDBVolumes, newSnapshotName)
- }
+ // Capture errors from the sender and receiver from their result channels.
+ errs := []error{}
+ aEndErr := <-aEndErrCh
+ if aEndErr != nil {
+ errs = append(errs, aEndErr)
}
- srcVol := srcPool.newVolume(drivers.VolumeTypeCustom, drivers.ContentTypeFS, srcVolName, nil)
- targetVol := b.newVolume(drivers.VolumeTypeCustom, drivers.ContentTypeFS, volName, config)
- err = b.driver.CreateVolumeFromCopy(targetVol, srcVol, copySnapshots, op)
- if err != nil {
- return err
+ bEndErr := <-bEndErrCh
+ if bEndErr != nil {
+ errs = append(errs, bEndErr)
+ }
+
+ if len(errs) > 0 {
+ return fmt.Errorf("Create custom volume from copy failed: %v", errs)
}
- revertDBVolumes = nil // Don't revert DB volumes.
return nil
}
From 786215e75dabffc672cd3abd467a967cc4efb80b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 30 Oct 2019 13:31:51 +0000
Subject: [PATCH 4/9] lxd/storage/backend/lxd: Updates migration functions to
accept progress tracker indicator
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/backend_lxd.go | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 368f7f5173..7216bb7932 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -384,9 +384,9 @@ func (b *lxdBackend) CreateCustomVolumeFromCopy(volName, desc string, config map
}
// MigrateCustomVolume sends a volume for migration.
-func (b *lxdBackend) MigrateCustomVolume(conn io.ReadWriteCloser, args migration.VolumeSourceArgs, op *operations.Operation) error {
+func (b *lxdBackend) MigrateCustomVolume(conn io.ReadWriteCloser, args migration.VolumeSourceArgs, trackProgress bool, op *operations.Operation) error {
vol := b.newVolume(drivers.VolumeTypeCustom, drivers.ContentTypeFS, args.Name, nil)
- err := b.driver.MigrateVolume(vol, conn, args, op)
+ err := b.driver.MigrateVolume(vol, conn, args, trackProgress, op)
if err != nil {
return err
}
@@ -395,7 +395,7 @@ func (b *lxdBackend) MigrateCustomVolume(conn io.ReadWriteCloser, args migration
}
// CreateCustomVolumeFromMigration receives a volume being migrated.
-func (b *lxdBackend) CreateCustomVolumeFromMigration(conn io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) error {
+func (b *lxdBackend) CreateCustomVolumeFromMigration(conn io.ReadWriteCloser, args migration.VolumeTargetArgs, trackProgress bool, op *operations.Operation) error {
// Create slice to record DB volumes created if revert needed later.
revertDBVolumes := []string{}
defer func() {
@@ -434,7 +434,7 @@ func (b *lxdBackend) CreateCustomVolumeFromMigration(conn io.ReadWriteCloser, ar
}
vol := b.newVolume(drivers.VolumeTypeCustom, drivers.ContentTypeFS, args.Name, args.Config)
- err = b.driver.CreateVolumeFromMigration(vol, conn, args, op)
+ err = b.driver.CreateVolumeFromMigration(vol, conn, args, trackProgress, op)
if err != nil {
return nil
}
From e752afc647705551d6bbb4c789e55c14ca36ffa5 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 30 Oct 2019 13:32:26 +0000
Subject: [PATCH 5/9] lxd/storage/backend/mock: Updates migration functions to
accept progress tracker indicator
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/backend_mock.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/storage/backend_mock.go b/lxd/storage/backend_mock.go
index 86562bc73e..d2987626af 100644
--- a/lxd/storage/backend_mock.go
+++ b/lxd/storage/backend_mock.go
@@ -168,11 +168,11 @@ func (b *mockBackend) DeleteCustomVolume(volName string, op *operations.Operatio
return nil
}
-func (b *mockBackend) MigrateCustomVolume(conn io.ReadWriteCloser, args migration.VolumeSourceArgs, op *operations.Operation) error {
+func (b *mockBackend) MigrateCustomVolume(conn io.ReadWriteCloser, args migration.VolumeSourceArgs, trackProgress bool, op *operations.Operation) error {
return nil
}
-func (b *mockBackend) CreateCustomVolumeFromMigration(conn io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) error {
+func (b *mockBackend) CreateCustomVolumeFromMigration(conn io.ReadWriteCloser, args migration.VolumeTargetArgs, trackProgress bool, op *operations.Operation) error {
return nil
}
From b78993cf27476721627e061ee7bc790eb054416a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 30 Oct 2019 13:33:02 +0000
Subject: [PATCH 6/9] lxd/storage/drivers/driver/common: Improves comment
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_common.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/storage/drivers/driver_common.go b/lxd/storage/drivers/driver_common.go
index f549975c3f..b2298ff330 100644
--- a/lxd/storage/drivers/driver_common.go
+++ b/lxd/storage/drivers/driver_common.go
@@ -70,8 +70,8 @@ func (d *common) validateVolume(volConfig map[string]string, driverRules map[str
return nil
}
-// MigrationType returns the type of transfer method used when doing migrations between pools
-// of the same type.
+// MigrationType returns the type of transfer methods to be used when doing migrations between pools
+// in preference order.
func (d *common) MigrationTypes(contentType ContentType) []migration.Type {
if contentType != ContentTypeFS {
return nil
From 0f3fa0c3b7ac54ccb2d9c01956b280878cd1e01b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 30 Oct 2019 13:33:32 +0000
Subject: [PATCH 7/9] lxd/storage/drivers/driver/dir: Updates migration
functions to accept progress tracker indicator
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/driver_dir.go | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/lxd/storage/drivers/driver_dir.go b/lxd/storage/drivers/driver_dir.go
index 19e856df35..c9e3cbd28f 100644
--- a/lxd/storage/drivers/driver_dir.go
+++ b/lxd/storage/drivers/driver_dir.go
@@ -15,6 +15,7 @@ import (
"github.com/lxc/lxd/lxd/storage/quota"
"github.com/lxc/lxd/shared"
"github.com/lxc/lxd/shared/api"
+ "github.com/lxc/lxd/shared/ioprogress"
"github.com/lxc/lxd/shared/units"
)
@@ -184,7 +185,7 @@ func (d *dir) CreateVolume(vol Volume, filler func(path string) error, op *opera
}
// MigrateVolume sends a volume for migration.
-func (d *dir) MigrateVolume(vol Volume, conn io.ReadWriteCloser, volSrcArgs migration.VolumeSourceArgs, op *operations.Operation) error {
+func (d *dir) MigrateVolume(vol Volume, conn io.ReadWriteCloser, volSrcArgs migration.VolumeSourceArgs, trackProgress bool, op *operations.Operation) error {
if volSrcArgs.MigrationType.FSType != migration.MigrationFSType_RSYNC {
return fmt.Errorf("Migration type not supported")
}
@@ -199,7 +200,10 @@ func (d *dir) MigrateVolume(vol Volume, conn io.ReadWriteCloser, volSrcArgs migr
// Send snapshot to recipient (ensure local snapshot volume is mounted if needed).
err = snapshot.MountTask(func(mountPath string, op *operations.Operation) error {
- wrapper := migration.ProgressTracker(op, "fs_progress", snapshot.name)
+ var wrapper *ioprogress.ProgressTracker
+ if trackProgress {
+ wrapper = migration.ProgressTracker(op, "fs_progress", snapshot.name)
+ }
path := shared.AddSlash(mountPath)
return rsync.Send(snapshot.name, path, conn, wrapper, volSrcArgs.MigrationType.Features, bwlimit, d.state.OS.ExecPath)
}, op)
@@ -210,14 +214,17 @@ func (d *dir) MigrateVolume(vol Volume, conn io.ReadWriteCloser, volSrcArgs migr
// Send volume to recipient (ensure local volume is mounted if needed).
return vol.MountTask(func(mountPath string, op *operations.Operation) error {
- wrapper := migration.ProgressTracker(op, "fs_progress", vol.name)
+ var wrapper *ioprogress.ProgressTracker
+ if trackProgress {
+ wrapper = migration.ProgressTracker(op, "fs_progress", vol.name)
+ }
path := shared.AddSlash(mountPath)
return rsync.Send(vol.name, path, conn, wrapper, volSrcArgs.MigrationType.Features, bwlimit, d.state.OS.ExecPath)
}, op)
}
// CreateVolumeFromMigration creates a volume being sent via a migration.
-func (d *dir) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, volTargetArgs migration.VolumeTargetArgs, op *operations.Operation) error {
+func (d *dir) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, volTargetArgs migration.VolumeTargetArgs, trackProgress bool, op *operations.Operation) error {
if vol.contentType != ContentTypeFS {
return fmt.Errorf("Content type not supported")
}
@@ -266,7 +273,10 @@ func (d *dir) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, vol
// Receive snapshot from sender (ensure local snapshot volume is mounted if needed).
err = snapshot.MountTask(func(mountPath string, op *operations.Operation) error {
- wrapper := migration.ProgressTracker(op, "fs_progress", snapshot.name)
+ var wrapper *ioprogress.ProgressTracker
+ if trackProgress {
+ wrapper = migration.ProgressTracker(op, "fs_progress", snapshot.name)
+ }
path := shared.AddSlash(mountPath)
return rsync.Recv(path, conn, wrapper, volTargetArgs.MigrationType.Features)
}, op)
@@ -299,7 +309,10 @@ func (d *dir) CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, vol
// Receive volume from sender (ensure local volume is mounted if needed).
err = vol.MountTask(func(mountPath string, op *operations.Operation) error {
- wrapper := migration.ProgressTracker(op, "fs_progress", vol.name)
+ var wrapper *ioprogress.ProgressTracker
+ if trackProgress {
+ wrapper = migration.ProgressTracker(op, "fs_progress", vol.name)
+ }
path := shared.AddSlash(mountPath)
return rsync.Recv(path, conn, wrapper, volTargetArgs.MigrationType.Features)
}, op)
From 0737102ab3e9e8ad8e2a2eef79c69a7d4bb8d018 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 30 Oct 2019 13:33:58 +0000
Subject: [PATCH 8/9] lxd/storage/drivers/interface: Updates migration
functions to accept progress tracker indicator
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/drivers/interface.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/storage/drivers/interface.go b/lxd/storage/drivers/interface.go
index c7d79fd84b..2e6024982c 100644
--- a/lxd/storage/drivers/interface.go
+++ b/lxd/storage/drivers/interface.go
@@ -59,6 +59,6 @@ type Driver interface {
// Migration.
MigrationTypes(contentType ContentType) []migration.Type
- MigrateVolume(vol Volume, conn io.ReadWriteCloser, volSrcArgs migration.VolumeSourceArgs, op *operations.Operation) error
- CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, volTargetArgs migration.VolumeTargetArgs, op *operations.Operation) error
+ MigrateVolume(vol Volume, conn io.ReadWriteCloser, volSrcArgs migration.VolumeSourceArgs, trackProgress bool, op *operations.Operation) error
+ CreateVolumeFromMigration(vol Volume, conn io.ReadWriteCloser, volTargetArgs migration.VolumeTargetArgs, trackProgress bool, op *operations.Operation) error
}
From 05f3e1a478f3813abf945657f591f63b5af4e6d9 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Wed, 30 Oct 2019 13:34:18 +0000
Subject: [PATCH 9/9] lxd/storage/interfaces: Updates migration functions to
accept progress tracker indicator
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/storage/interfaces.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/storage/interfaces.go b/lxd/storage/interfaces.go
index d1d3cbdbba..3412d03351 100644
--- a/lxd/storage/interfaces.go
+++ b/lxd/storage/interfaces.go
@@ -88,6 +88,6 @@ type Pool interface {
// Custom volume migration.
MigrationTypes(contentType drivers.ContentType) []migration.Type
- CreateCustomVolumeFromMigration(conn io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) error
- MigrateCustomVolume(conn io.ReadWriteCloser, args migration.VolumeSourceArgs, op *operations.Operation) error
+ CreateCustomVolumeFromMigration(conn io.ReadWriteCloser, args migration.VolumeTargetArgs, trackProgress bool, op *operations.Operation) error
+ MigrateCustomVolume(conn io.ReadWriteCloser, args migration.VolumeSourceArgs, trackProgress bool, op *operations.Operation) error
}
More information about the lxc-devel
mailing list