The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6367

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
- Updates Storage volume copy to use the migration logic with a bi-directional in-memory pipe.
- Adds progress tracker indicator to storage migration functions so that when doing a local copy one can disable the progress tracker on one side.
From 19100009dea691fa57b8fa0e24f6db522e82c7df Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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
 }
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to