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

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) ===
Includes https://github.com/lxc/lxd/pull/6509
From 5530061122c032c3f0f3b0ba95e3890229fd38fe Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 26 Nov 2019 10:19:18 +0000
Subject: [PATCH 1/8] lxd/storage: Renames interfaces.go to pool_interface.go

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/{interfaces.go => pool_interface.go} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename lxd/storage/{interfaces.go => pool_interface.go} (100%)

diff --git a/lxd/storage/interfaces.go b/lxd/storage/pool_interface.go
similarity index 100%
rename from lxd/storage/interfaces.go
rename to lxd/storage/pool_interface.go

From b6c98a2fc835e554607c3f0060c387748352fa16 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 26 Nov 2019 10:19:41 +0000
Subject: [PATCH 2/8] lxd/storage/pool/interface: Removes Instance interface

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/pool_interface.go | 54 +++++++++++++----------------------
 1 file changed, 20 insertions(+), 34 deletions(-)

diff --git a/lxd/storage/pool_interface.go b/lxd/storage/pool_interface.go
index 11695abe4b..ca821cc4a9 100644
--- a/lxd/storage/pool_interface.go
+++ b/lxd/storage/pool_interface.go
@@ -3,9 +3,7 @@ package storage
 import (
        "io"
 
-       deviceConfig "github.com/lxc/lxd/lxd/device/config"
        "github.com/lxc/lxd/lxd/instance"
-       "github.com/lxc/lxd/lxd/instance/instancetype"
        "github.com/lxc/lxd/lxd/migration"
        "github.com/lxc/lxd/lxd/operations"
        "github.com/lxc/lxd/lxd/state"
@@ -13,18 +11,6 @@ import (
        "github.com/lxc/lxd/shared/api"
 )
 
-// Instance represents the storage relevant subset of a LXD instance.
-type Instance interface {
-       Name() string
-       Project() string
-       Type() instancetype.Type
-
-       IsRunning() bool
-       IsSnapshot() bool
-       DeferTemplateApply(trigger string) error
-       ExpandedDevices() deviceConfig.Devices
-}
-
 // Pool represents a LXD storage pool.
 type Pool interface {
        // Internal.
@@ -42,32 +28,32 @@ type Pool interface {
        Unmount() (bool, error)
 
        // Instances.
-       CreateInstance(inst Instance, op *operations.Operation) error
-       CreateInstanceFromBackup(inst Instance, sourcePath string, op 
*operations.Operation) error
-       CreateInstanceFromCopy(inst Instance, src Instance, snapshots bool, op 
*operations.Operation) error
-       CreateInstanceFromImage(inst Instance, fingerprint string, op 
*operations.Operation) error
-       CreateInstanceFromMigration(inst Instance, conn io.ReadWriteCloser, 
args migration.VolumeTargetArgs, op *operations.Operation) error
-       RenameInstance(inst Instance, newName string, op *operations.Operation) 
error
-       DeleteInstance(inst Instance, op *operations.Operation) error
-
-       MigrateInstance(inst Instance, conn io.ReadWriteCloser, args 
migration.VolumeSourceArgs, op *operations.Operation) error
+       CreateInstance(inst instance.Instance, op *operations.Operation) error
+       CreateInstanceFromBackup(inst instance.Instance, sourcePath string, op 
*operations.Operation) error
+       CreateInstanceFromCopy(inst instance.Instance, src instance.Instance, 
snapshots bool, op *operations.Operation) error
+       CreateInstanceFromImage(inst instance.Instance, fingerprint string, op 
*operations.Operation) error
+       CreateInstanceFromMigration(inst instance.Instance, conn 
io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) 
error
+       RenameInstance(inst instance.Instance, newName string, op 
*operations.Operation) error
+       DeleteInstance(inst instance.Instance, op *operations.Operation) error
+
+       MigrateInstance(inst instance.Instance, conn io.ReadWriteCloser, args 
migration.VolumeSourceArgs, op *operations.Operation) error
        RefreshInstance(inst instance.Instance, src instance.Instance, 
srcSnapshots []instance.Instance, op *operations.Operation) error
-       BackupInstance(inst Instance, targetPath string, optimized bool, 
snapshots bool, op *operations.Operation) error
+       BackupInstance(inst instance.Instance, targetPath string, optimized 
bool, snapshots bool, op *operations.Operation) error
 
-       GetInstanceUsage(inst Instance) (int64, error)
-       SetInstanceQuota(inst Instance, size string, op *operations.Operation) 
error
+       GetInstanceUsage(inst instance.Instance) (int64, error)
+       SetInstanceQuota(inst instance.Instance, size string, op 
*operations.Operation) error
 
-       MountInstance(inst Instance, op *operations.Operation) (bool, error)
-       UnmountInstance(inst Instance, op *operations.Operation) (bool, error)
-       GetInstanceDisk(inst Instance) (string, error)
+       MountInstance(inst instance.Instance, op *operations.Operation) (bool, 
error)
+       UnmountInstance(inst instance.Instance, op *operations.Operation) 
(bool, error)
+       GetInstanceDisk(inst instance.Instance) (string, error)
 
        // Instance snapshots.
        CreateInstanceSnapshot(inst instance.Instance, src instance.Instance, 
op *operations.Operation) error
-       RenameInstanceSnapshot(inst Instance, newName string, op 
*operations.Operation) error
-       DeleteInstanceSnapshot(inst Instance, op *operations.Operation) error
-       RestoreInstanceSnapshot(inst Instance, op *operations.Operation) error
-       MountInstanceSnapshot(inst Instance, op *operations.Operation) (bool, 
error)
-       UnmountInstanceSnapshot(inst Instance, op *operations.Operation) (bool, 
error)
+       RenameInstanceSnapshot(inst instance.Instance, newName string, op 
*operations.Operation) error
+       DeleteInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) error
+       RestoreInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) error
+       MountInstanceSnapshot(inst instance.Instance, op *operations.Operation) 
(bool, error)
+       UnmountInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) (bool, error)
 
        // Images.
        EnsureImage(fingerprint string, op *operations.Operation) error

From 4762e9c4cdb64b2fdbb2ba5a4d9c24d9c6752185 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 26 Nov 2019 10:20:03 +0000
Subject: [PATCH 3/8] lxd/storage: Switches to use instance.Instance interface

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/backend_lxd.go  | 38 ++++++++++++++++++-------------------
 lxd/storage/backend_mock.go | 38 ++++++++++++++++++-------------------
 lxd/storage/load.go         |  3 ++-
 3 files changed, 40 insertions(+), 39 deletions(-)

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 76f85c0e90..ac8ea670a3 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -278,7 +278,7 @@ func (b *lxdBackend) 
removeInstanceSnapshotSymlinkIfUnused(instanceType instance
 }
 
 // CreateInstance creates an empty instance.
-func (b *lxdBackend) CreateInstance(inst Instance, op *operations.Operation) 
error {
+func (b *lxdBackend) CreateInstance(inst instance.Instance, op 
*operations.Operation) error {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name()})
        logger.Debug("CreateInstance started")
        defer logger.Debug("CreateInstance finished")
@@ -327,12 +327,12 @@ func (b *lxdBackend) CreateInstance(inst Instance, op 
*operations.Operation) err
        return nil
 }
 
-func (b *lxdBackend) CreateInstanceFromBackup(inst Instance, sourcePath 
string, op *operations.Operation) error {
+func (b *lxdBackend) CreateInstanceFromBackup(inst instance.Instance, 
sourcePath string, op *operations.Operation) error {
        return ErrNotImplemented
 }
 
 // CreateInstanceFromCopy copies an instance volume and optionally its 
snapshots to new volume(s).
-func (b *lxdBackend) CreateInstanceFromCopy(inst Instance, src Instance, 
snapshots bool, op *operations.Operation) error {
+func (b *lxdBackend) CreateInstanceFromCopy(inst instance.Instance, src 
instance.Instance, snapshots bool, op *operations.Operation) error {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name(), "src": src.Name(), "snapshots": 
snapshots})
        logger.Debug("CreateInstanceFromCopy started")
        defer logger.Debug("CreateInstanceFromCopy finished")
@@ -632,7 +632,7 @@ func (b *lxdBackend) imageFiller(fingerprint string, op 
*operations.Operation) f
 }
 
 // CreateInstanceFromImage creates a new volume for an instance populated with 
the image requested.
-func (b *lxdBackend) CreateInstanceFromImage(inst Instance, fingerprint 
string, op *operations.Operation) error {
+func (b *lxdBackend) CreateInstanceFromImage(inst instance.Instance, 
fingerprint string, op *operations.Operation) error {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name()})
        logger.Debug("CreateInstanceFromImage started")
        defer logger.Debug("CreateInstanceFromImage finished")
@@ -703,7 +703,7 @@ func (b *lxdBackend) CreateInstanceFromImage(inst Instance, 
fingerprint string,
 
 // CreateInstanceFromMigration receives an instance being migrated.
 // The args.Name and args.Config fields are ignored and, instance properties 
are used instead.
-func (b *lxdBackend) CreateInstanceFromMigration(inst Instance, conn 
io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) 
error {
+func (b *lxdBackend) CreateInstanceFromMigration(inst instance.Instance, conn 
io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) 
error {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name(), "args": args})
        logger.Debug("CreateInstanceFromMigration started")
        defer logger.Debug("CreateInstanceFromMigration finished")
@@ -746,7 +746,7 @@ func (b *lxdBackend) CreateInstanceFromMigration(inst 
Instance, conn io.ReadWrit
 }
 
 // RenameInstance renames the instance's root volume and any snapshot volumes.
-func (b *lxdBackend) RenameInstance(inst Instance, newName string, op 
*operations.Operation) error {
+func (b *lxdBackend) RenameInstance(inst instance.Instance, newName string, op 
*operations.Operation) error {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name(), "newName": newName})
        logger.Debug("RenameInstance started")
        defer logger.Debug("RenameInstance finished")
@@ -853,7 +853,7 @@ func (b *lxdBackend) RenameInstance(inst Instance, newName 
string, op *operation
 }
 
 // DeleteInstance removes the instance's root volume (all snapshots need to be 
removed first).
-func (b *lxdBackend) DeleteInstance(inst Instance, op *operations.Operation) 
error {
+func (b *lxdBackend) DeleteInstance(inst instance.Instance, op 
*operations.Operation) error {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name()})
        logger.Debug("DeleteInstance started")
        defer logger.Debug("DeleteInstance finished")
@@ -917,7 +917,7 @@ func (b *lxdBackend) DeleteInstance(inst Instance, op 
*operations.Operation) err
 
 // MigrateInstance sends an instance volume for migration.
 // The args.Name field is ignored and the name of the instance is used instead.
-func (b *lxdBackend) MigrateInstance(inst Instance, conn io.ReadWriteCloser, 
args migration.VolumeSourceArgs, op *operations.Operation) error {
+func (b *lxdBackend) MigrateInstance(inst instance.Instance, conn 
io.ReadWriteCloser, args migration.VolumeSourceArgs, op *operations.Operation) 
error {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name(), "args": args})
        logger.Debug("MigrateInstance started")
        defer logger.Debug("MigrateInstance finished")
@@ -948,12 +948,12 @@ func (b *lxdBackend) MigrateInstance(inst Instance, conn 
io.ReadWriteCloser, arg
        return nil
 }
 
-func (b *lxdBackend) BackupInstance(inst Instance, targetPath string, 
optimized bool, snapshots bool, op *operations.Operation) error {
+func (b *lxdBackend) BackupInstance(inst instance.Instance, targetPath string, 
optimized bool, snapshots bool, op *operations.Operation) error {
        return ErrNotImplemented
 }
 
 // GetInstanceUsage returns the disk usage of the instance's root volume.
-func (b *lxdBackend) GetInstanceUsage(inst Instance) (int64, error) {
+func (b *lxdBackend) GetInstanceUsage(inst instance.Instance) (int64, error) {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name()})
        logger.Debug("GetInstanceUsage started")
        defer logger.Debug("GetInstanceUsage finished")
@@ -968,7 +968,7 @@ func (b *lxdBackend) GetInstanceUsage(inst Instance) 
(int64, error) {
 // SetInstanceQuota sets the quota on the instance's root volume.
 // Returns ErrRunningQuotaResizeNotSupported if the instance is running and 
the storage driver
 // doesn't support resizing whilst the instance is running.
-func (b *lxdBackend) SetInstanceQuota(inst Instance, size string, op 
*operations.Operation) error {
+func (b *lxdBackend) SetInstanceQuota(inst instance.Instance, size string, op 
*operations.Operation) error {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name()})
        logger.Debug("SetInstanceQuota started")
        defer logger.Debug("SetInstanceQuota finished")
@@ -990,7 +990,7 @@ func (b *lxdBackend) SetInstanceQuota(inst Instance, size 
string, op *operations
 }
 
 // MountInstance mounts the instance's root volume.
-func (b *lxdBackend) MountInstance(inst Instance, op *operations.Operation) 
(bool, error) {
+func (b *lxdBackend) MountInstance(inst instance.Instance, op 
*operations.Operation) (bool, error) {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name()})
        logger.Debug("MountInstance started")
        defer logger.Debug("MountInstance finished")
@@ -1008,7 +1008,7 @@ func (b *lxdBackend) MountInstance(inst Instance, op 
*operations.Operation) (boo
 }
 
 // UnmountInstance unmounts the instance's root volume.
-func (b *lxdBackend) UnmountInstance(inst Instance, op *operations.Operation) 
(bool, error) {
+func (b *lxdBackend) UnmountInstance(inst instance.Instance, op 
*operations.Operation) (bool, error) {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name()})
        logger.Debug("UnmountInstance started")
        defer logger.Debug("UnmountInstance finished")
@@ -1026,7 +1026,7 @@ func (b *lxdBackend) UnmountInstance(inst Instance, op 
*operations.Operation) (b
 }
 
 // GetInstanceDisk returns the location of the disk.
-func (b *lxdBackend) GetInstanceDisk(inst Instance) (string, error) {
+func (b *lxdBackend) GetInstanceDisk(inst instance.Instance) (string, error) {
        if inst.Type() != instancetype.VM {
                return "", ErrNotImplemented
        }
@@ -1104,7 +1104,7 @@ func (b *lxdBackend) CreateInstanceSnapshot(inst 
instance.Instance, src instance
 }
 
 // RenameInstanceSnapshot renames an instance snapshot.
-func (b *lxdBackend) RenameInstanceSnapshot(inst Instance, newName string, op 
*operations.Operation) error {
+func (b *lxdBackend) RenameInstanceSnapshot(inst instance.Instance, newName 
string, op *operations.Operation) error {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name(), "newName": newName})
        logger.Debug("RenameInstanceSnapshot started")
        defer logger.Debug("RenameInstanceSnapshot finished")
@@ -1152,7 +1152,7 @@ func (b *lxdBackend) RenameInstanceSnapshot(inst 
Instance, newName string, op *o
 }
 
 // DeleteInstanceSnapshot removes the snapshot volume for the supplied 
snapshot instance.
-func (b *lxdBackend) DeleteInstanceSnapshot(inst Instance, op 
*operations.Operation) error {
+func (b *lxdBackend) DeleteInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) error {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name()})
        logger.Debug("DeleteInstanceSnapshot started")
        defer logger.Debug("DeleteInstanceSnapshot finished")
@@ -1199,13 +1199,13 @@ func (b *lxdBackend) DeleteInstanceSnapshot(inst 
Instance, op *operations.Operat
        return nil
 }
 
-func (b *lxdBackend) RestoreInstanceSnapshot(inst Instance, op 
*operations.Operation) error {
+func (b *lxdBackend) RestoreInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) error {
        return ErrNotImplemented
 }
 
 // MountInstanceSnapshot mounts an instance snapshot. It is mounted as read 
only so that the
 // snapshot cannot be modified.
-func (b *lxdBackend) MountInstanceSnapshot(inst Instance, op 
*operations.Operation) (bool, error) {
+func (b *lxdBackend) MountInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) (bool, error) {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name()})
        logger.Debug("MountInstanceSnapshot started")
        defer logger.Debug("MountInstanceSnapshot finished")
@@ -1230,7 +1230,7 @@ func (b *lxdBackend) MountInstanceSnapshot(inst Instance, 
op *operations.Operati
 }
 
 // UnmountInstanceSnapshot unmounts an instance snapshot.
-func (b *lxdBackend) UnmountInstanceSnapshot(inst Instance, op 
*operations.Operation) (bool, error) {
+func (b *lxdBackend) UnmountInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) (bool, error) {
        logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name()})
        logger.Debug("UnmountInstanceSnapshot started")
        defer logger.Debug("UnmountInstanceSnapshot finished")
diff --git a/lxd/storage/backend_mock.go b/lxd/storage/backend_mock.go
index c8e14c1aa1..3fb98dec58 100644
--- a/lxd/storage/backend_mock.go
+++ b/lxd/storage/backend_mock.go
@@ -59,35 +59,35 @@ func (b *mockBackend) Unmount() (bool, error) {
        return true, nil
 }
 
-func (b *mockBackend) CreateInstance(i Instance, op *operations.Operation) 
error {
+func (b *mockBackend) CreateInstance(inst instance.Instance, op 
*operations.Operation) error {
        return nil
 }
 
-func (b *mockBackend) CreateInstanceFromBackup(i Instance, sourcePath string, 
op *operations.Operation) error {
+func (b *mockBackend) CreateInstanceFromBackup(inst instance.Instance, 
sourcePath string, op *operations.Operation) error {
        return nil
 }
 
-func (b *mockBackend) CreateInstanceFromCopy(i Instance, src Instance, 
snapshots bool, op *operations.Operation) error {
+func (b *mockBackend) CreateInstanceFromCopy(inst instance.Instance, src 
instance.Instance, snapshots bool, op *operations.Operation) error {
        return nil
 }
 
-func (b *mockBackend) CreateInstanceFromImage(i Instance, fingerprint string, 
op *operations.Operation) error {
+func (b *mockBackend) CreateInstanceFromImage(inst instance.Instance, 
fingerprint string, op *operations.Operation) error {
        return nil
 }
 
-func (b *mockBackend) CreateInstanceFromMigration(inst Instance, conn 
io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) 
error {
+func (b *mockBackend) CreateInstanceFromMigration(inst instance.Instance, conn 
io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) 
error {
        return nil
 }
 
-func (b *mockBackend) RenameInstance(i Instance, newName string, op 
*operations.Operation) error {
+func (b *mockBackend) RenameInstance(inst instance.Instance, newName string, 
op *operations.Operation) error {
        return nil
 }
 
-func (b *mockBackend) DeleteInstance(i Instance, op *operations.Operation) 
error {
+func (b *mockBackend) DeleteInstance(inst instance.Instance, op 
*operations.Operation) error {
        return nil
 }
 
-func (b *mockBackend) MigrateInstance(inst Instance, conn io.ReadWriteCloser, 
args migration.VolumeSourceArgs, op *operations.Operation) error {
+func (b *mockBackend) MigrateInstance(inst instance.Instance, conn 
io.ReadWriteCloser, args migration.VolumeSourceArgs, op *operations.Operation) 
error {
        return nil
 }
 
@@ -95,27 +95,27 @@ func (b *mockBackend) RefreshInstance(i instance.Instance, 
src instance.Instance
        return nil
 }
 
-func (b *mockBackend) BackupInstance(i Instance, targetPath string, optimized 
bool, snapshots bool, op *operations.Operation) error {
+func (b *mockBackend) BackupInstance(inst instance.Instance, targetPath 
string, optimized bool, snapshots bool, op *operations.Operation) error {
        return nil
 }
 
-func (b *mockBackend) GetInstanceUsage(i Instance) (int64, error) {
+func (b *mockBackend) GetInstanceUsage(inst instance.Instance) (int64, error) {
        return 0, nil
 }
 
-func (b *mockBackend) SetInstanceQuota(i Instance, size string, op 
*operations.Operation) error {
+func (b *mockBackend) SetInstanceQuota(inst instance.Instance, size string, op 
*operations.Operation) error {
        return nil
 }
 
-func (b *mockBackend) MountInstance(i Instance, op *operations.Operation) 
(bool, error) {
+func (b *mockBackend) MountInstance(inst instance.Instance, op 
*operations.Operation) (bool, error) {
        return true, nil
 }
 
-func (b *mockBackend) UnmountInstance(i Instance, op *operations.Operation) 
(bool, error) {
+func (b *mockBackend) UnmountInstance(inst instance.Instance, op 
*operations.Operation) (bool, error) {
        return true, nil
 }
 
-func (b *mockBackend) GetInstanceDisk(i Instance) (string, error) {
+func (b *mockBackend) GetInstanceDisk(inst instance.Instance) (string, error) {
        return "", nil
 }
 
@@ -123,23 +123,23 @@ func (b *mockBackend) CreateInstanceSnapshot(i 
instance.Instance, src instance.I
        return nil
 }
 
-func (b *mockBackend) RenameInstanceSnapshot(i Instance, newName string, op 
*operations.Operation) error {
+func (b *mockBackend) RenameInstanceSnapshot(inst instance.Instance, newName 
string, op *operations.Operation) error {
        return nil
 }
 
-func (b *mockBackend) DeleteInstanceSnapshot(i Instance, op 
*operations.Operation) error {
+func (b *mockBackend) DeleteInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) error {
        return nil
 }
 
-func (b *mockBackend) RestoreInstanceSnapshot(i Instance, op 
*operations.Operation) error {
+func (b *mockBackend) RestoreInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) error {
        return nil
 }
 
-func (b *mockBackend) MountInstanceSnapshot(i Instance, op 
*operations.Operation) (bool, error) {
+func (b *mockBackend) MountInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) (bool, error) {
        return true, nil
 }
 
-func (b *mockBackend) UnmountInstanceSnapshot(i Instance, op 
*operations.Operation) (bool, error) {
+func (b *mockBackend) UnmountInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) (bool, error) {
        return true, nil
 }
 
diff --git a/lxd/storage/load.go b/lxd/storage/load.go
index bdad09351b..c530bcf9cd 100644
--- a/lxd/storage/load.go
+++ b/lxd/storage/load.go
@@ -5,6 +5,7 @@ import (
        "strings"
 
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/instance"
        "github.com/lxc/lxd/lxd/operations"
        "github.com/lxc/lxd/lxd/state"
        "github.com/lxc/lxd/lxd/storage/drivers"
@@ -151,7 +152,7 @@ func GetPoolByName(state *state.State, name string) (Pool, 
error) {
 // GetPoolByInstance retrieves the pool from the database using the instance's 
pool.
 // If the pool's driver is not recognised then drivers.ErrUnknownDriver is 
returned. If the pool's
 // driver does not support the instance's type then drivers.ErrNotImplemented 
is returned.
-func GetPoolByInstance(s *state.State, inst Instance) (Pool, error) {
+func GetPoolByInstance(s *state.State, inst instance.Instance) (Pool, error) {
        poolName, err := s.Cluster.InstancePool(inst.Project(), inst.Name())
        if err != nil {
                return nil, err

From 9b80beed14fb4b67c61ee844150d6589ef857db9 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 26 Nov 2019 09:15:45 +0000
Subject: [PATCH 4/8] lxd/container/put: Renames containerSnapRestore to
 instanceSnapRestore

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/container_put.go | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lxd/container_put.go b/lxd/container_put.go
index de99565ace..0e221afb13 100644
--- a/lxd/container_put.go
+++ b/lxd/container_put.go
@@ -92,7 +92,7 @@ func containerPut(d *Daemon, r *http.Request) 
response.Response {
        } else {
                // Snapshot Restore
                do = func(op *operations.Operation) error {
-                       return containerSnapRestore(d.State(), project, name, 
configRaw.Restore, configRaw.Stateful)
+                       return instanceSnapRestore(d.State(), project, name, 
configRaw.Restore, configRaw.Stateful)
                }
 
                opType = db.OperationSnapshotRestore
@@ -109,13 +109,13 @@ func containerPut(d *Daemon, r *http.Request) 
response.Response {
        return operations.OperationResponse(op)
 }
 
-func containerSnapRestore(s *state.State, project, name, snap string, stateful 
bool) error {
+func instanceSnapRestore(s *state.State, project, name, snap string, stateful 
bool) error {
        // normalize snapshot name
        if !shared.IsSnapshot(snap) {
                snap = name + shared.SnapshotDelimiter + snap
        }
 
-       c, err := instanceLoadByProjectAndName(s, project, name)
+       inst, err := instanceLoadByProjectAndName(s, project, name)
        if err != nil {
                return err
        }
@@ -130,7 +130,7 @@ func containerSnapRestore(s *state.State, project, name, 
snap string, stateful b
                }
        }
 
-       err = c.Restore(source, stateful)
+       err = inst.Restore(source, stateful)
        if err != nil {
                return err
        }

From a249a3100af6eb96ddf4fc9349a8a244311c9478 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 26 Nov 2019 09:36:56 +0000
Subject: [PATCH 5/8] lxd/container/lxc: Links snapshot Restore() to new
 storage pkg

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/container_lxc.go | 106 +++++++++++++++++++++++++++----------------
 1 file changed, 67 insertions(+), 39 deletions(-)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index c93b7c22bf..4a8a41a203 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -3316,26 +3316,41 @@ func (c *containerLXC) Backups() ([]backup.Backup, 
error) {
        return backups, nil
 }
 
+// Restore restores a snapshot.
 func (c *containerLXC) Restore(sourceContainer instance.Instance, stateful 
bool) error {
        var ctxMap log.Ctx
 
-       // Initialize storage interface for the container.
-       err := c.initStorage()
-       if err != nil {
-               return err
-       }
+       // Initialize storage interface for the container and mount the rootfs 
for criu state check.
+       // Check if we can load new storage layer for pool driver type.
+       pool, err := storagePools.GetPoolByInstance(c.state, c)
+       if err != storageDrivers.ErrUnknownDriver && err != 
storageDrivers.ErrNotImplemented {
+               if err != nil {
+                       return err
+               }
 
-       ourStart, err := c.StorageStart()
-       if err != nil {
-               return err
-       }
-       if ourStart {
-               defer c.StorageStop()
+               ourStart, err := pool.MountInstance(c, nil)
+               if err != nil {
+                       return err
+               }
+               if ourStart {
+                       defer pool.UnmountInstance(c, nil)
+               }
+       } else {
+               err = c.initStorage()
+               if err != nil {
+                       return err
+               }
+
+               ourStart, err := c.StorageStart()
+               if err != nil {
+                       return err
+               }
+               if ourStart {
+                       defer c.StorageStop()
+               }
        }
 
-       /* let's also check for CRIU if necessary, before doing a bunch of
-        * filesystem manipulations
-        */
+       // Check for CRIU if necessary, before doing a bunch of filesystem 
manipulations.
        if shared.PathExists(c.StatePath()) {
                _, err := exec.LookPath("criu")
                if err != nil {
@@ -3343,14 +3358,14 @@ func (c *containerLXC) Restore(sourceContainer 
instance.Instance, stateful bool)
                }
        }
 
-       // Stop the container
+       // Stop the container.
        wasRunning := false
        if c.IsRunning() {
                wasRunning = true
 
                ephemeral := c.IsEphemeral()
                if ephemeral {
-                       // Unset ephemeral flag
+                       // Unset ephemeral flag.
                        args := db.InstanceArgs{
                                Architecture: c.Architecture(),
                                Config:       c.LocalConfig(),
@@ -3368,7 +3383,7 @@ func (c *containerLXC) Restore(sourceContainer 
instance.Instance, stateful bool)
                                return err
                        }
 
-                       // On function return, set the flag back on
+                       // On function return, set the flag back on.
                        defer func() {
                                args.Ephemeral = ephemeral
                                c.Update(args, true)
@@ -3382,12 +3397,22 @@ func (c *containerLXC) Restore(sourceContainer 
instance.Instance, stateful bool)
                }
 
                // Ensure that storage is mounted for state path checks.
-               ourStart, err := c.StorageStart()
-               if err != nil {
-                       return err
-               }
-               if ourStart {
-                       defer c.StorageStop()
+               if pool != nil {
+                       ourStart, err := pool.MountInstance(c, nil)
+                       if err != nil {
+                               return err
+                       }
+                       if ourStart {
+                               defer pool.UnmountInstance(c, nil)
+                       }
+               } else {
+                       ourStart, err := c.StorageStart()
+                       if err != nil {
+                               return err
+                       }
+                       if ourStart {
+                               defer c.StorageStop()
+                       }
                }
        }
 
@@ -3401,14 +3426,21 @@ func (c *containerLXC) Restore(sourceContainer 
instance.Instance, stateful bool)
 
        logger.Info("Restoring container", ctxMap)
 
-       // Restore the rootfs
-       err = c.storage.ContainerRestore(c, sourceContainer)
-       if err != nil {
-               logger.Error("Failed restoring container filesystem", ctxMap)
-               return err
+       // Restore the rootfs.
+       if pool != nil {
+               err = pool.RestoreInstanceSnapshot(c, sourceContainer, nil)
+               if err != nil {
+                       return err
+               }
+       } else {
+               err = c.storage.ContainerRestore(c, sourceContainer)
+               if err != nil {
+                       logger.Error("Failed restoring container filesystem", 
ctxMap)
+                       return err
+               }
        }
 
-       // Restore the configuration
+       // Restore the configuration.
        args := db.InstanceArgs{
                Architecture: sourceContainer.Architecture(),
                Config:       sourceContainer.LocalConfig(),
@@ -3427,16 +3459,14 @@ func (c *containerLXC) Restore(sourceContainer 
instance.Instance, stateful bool)
                return err
        }
 
-       // The old backup file may be out of date (e.g. it doesn't have all the
-       // current snapshots of the container listed); let's write a new one to
-       // be safe.
+       // The old backup file may be out of date (e.g. it doesn't have all the 
current snapshots of
+       // the container listed); let's write a new one to be safe.
        err = writeBackupFile(c)
        if err != nil {
                return err
        }
 
-       // If the container wasn't running but was stateful, should we restore
-       // it as running?
+       // If the container wasn't running but was stateful, should we restore 
it as running?
        if stateful == true {
                if !shared.PathExists(c.StatePath()) {
                        return fmt.Errorf("Stateful snapshot restore requested 
by snapshot is stateless")
@@ -3455,14 +3485,13 @@ func (c *containerLXC) Restore(sourceContainer 
instance.Instance, stateful bool)
                        preDumpDir:   "",
                }
 
-               // Checkpoint
+               // Checkpoint.
                err := c.Migrate(&criuMigrationArgs)
                if err != nil {
                        return err
                }
 
-               // Remove the state from the parent container; we only keep
-               // this in snapshots.
+               // Remove the state from the parent container; we only keep 
this in snapshots.
                err2 := os.RemoveAll(c.StatePath())
                if err2 != nil {
                        logger.Error("Failed to delete snapshot state", 
log.Ctx{"path": c.StatePath(), "err": err2})
@@ -3483,14 +3512,13 @@ func (c *containerLXC) Restore(sourceContainer 
instance.Instance, stateful bool)
                        "snapshot_name": c.name,
                })
 
-       // Restart the container
+       // Restart the container.
        if wasRunning {
                logger.Info("Restored container", ctxMap)
                return c.Start(false)
        }
 
        logger.Info("Restored container", ctxMap)
-
        return nil
 }
 

From 8c9b1439f0c80930aff5ad3ba37f4a1b9bd80ad7 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 26 Nov 2019 09:37:27 +0000
Subject: [PATCH 6/8] lxd/storage/interfaces: RestoreInstanceSnapshot signature

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/pool_interface.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lxd/storage/pool_interface.go b/lxd/storage/pool_interface.go
index ca821cc4a9..e00cbcc24f 100644
--- a/lxd/storage/pool_interface.go
+++ b/lxd/storage/pool_interface.go
@@ -51,7 +51,7 @@ type Pool interface {
        CreateInstanceSnapshot(inst instance.Instance, src instance.Instance, 
op *operations.Operation) error
        RenameInstanceSnapshot(inst instance.Instance, newName string, op 
*operations.Operation) error
        DeleteInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) error
-       RestoreInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) error
+       RestoreInstanceSnapshot(inst instance.Instance, src instance.Instance, 
op *operations.Operation) error
        MountInstanceSnapshot(inst instance.Instance, op *operations.Operation) 
(bool, error)
        UnmountInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) (bool, error)
 

From 4ee7fee451566eaafe68e171c17e78bf66a4f3dc Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 26 Nov 2019 09:37:48 +0000
Subject: [PATCH 7/8] lxd/storage/backend/mock: RestoreInstanceSnapshot
 signature

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/backend_mock.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lxd/storage/backend_mock.go b/lxd/storage/backend_mock.go
index 3fb98dec58..cb3a464b71 100644
--- a/lxd/storage/backend_mock.go
+++ b/lxd/storage/backend_mock.go
@@ -131,7 +131,7 @@ func (b *mockBackend) DeleteInstanceSnapshot(inst 
instance.Instance, op *operati
        return nil
 }
 
-func (b *mockBackend) RestoreInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) error {
+func (b *mockBackend) RestoreInstanceSnapshot(inst instance.Instance, src 
instance.Instance, op *operations.Operation) error {
        return nil
 }
 

From 47a7e123e85bbd17afd3b5b4175cff10b9e56619 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 26 Nov 2019 10:14:04 +0000
Subject: [PATCH 8/8] lxd/storage/backend/lxd: Implements
 RestoreInstanceSnapshot

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/backend_lxd.go | 62 +++++++++++++++++++++++++++++++++++---
 1 file changed, 58 insertions(+), 4 deletions(-)

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index ac8ea670a3..7693bf90dc 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -1060,11 +1060,11 @@ func (b *lxdBackend) CreateInstanceSnapshot(inst 
instance.Instance, src instance
        }
 
        if !inst.IsSnapshot() {
-               return fmt.Errorf("Instance must be snapshot")
+               return fmt.Errorf("Instance must be a snapshot")
        }
 
        if src.IsSnapshot() {
-               return fmt.Errorf("Source instance cannot be snapshot")
+               return fmt.Errorf("Source instance cannot be a snapshot")
        }
 
        // Check we can convert the instance to the volume type needed.
@@ -1199,8 +1199,62 @@ func (b *lxdBackend) DeleteInstanceSnapshot(inst 
instance.Instance, op *operatio
        return nil
 }
 
-func (b *lxdBackend) RestoreInstanceSnapshot(inst instance.Instance, op 
*operations.Operation) error {
-       return ErrNotImplemented
+// RestoreInstanceSnapshot restores an instance snapshot.
+func (b *lxdBackend) RestoreInstanceSnapshot(inst instance.Instance, src 
instance.Instance, op *operations.Operation) error {
+       logger := logging.AddContext(b.logger, log.Ctx{"project": 
inst.Project(), "instance": inst.Name(), "src": src.Name()})
+       logger.Debug("RestoreInstanceSnapshot started")
+       defer logger.Debug("RestoreInstanceSnapshot finished")
+
+       if inst.Type() != src.Type() {
+               return fmt.Errorf("Instance types must match")
+       }
+
+       if inst.IsSnapshot() {
+               return fmt.Errorf("Instance must not be snapshot")
+       }
+
+       if !src.IsSnapshot() {
+               return fmt.Errorf("Source instance must be a snapshot")
+       }
+
+       // Target instance must not be running.
+       if inst.IsRunning() {
+               return fmt.Errorf("Instance must not be running to restore")
+       }
+
+       // Check we can convert the instance to the volume type needed.
+       volType, err := InstanceTypeToVolumeType(inst.Type())
+       if err != nil {
+               return err
+       }
+
+       contentType := drivers.ContentTypeFS
+       if inst.Type() == instancetype.VM {
+               contentType = drivers.ContentTypeBlock
+       }
+
+       // Find the root device config for source snapshot instance.
+       _, rootDiskConf, err := 
shared.GetRootDiskDevice(src.ExpandedDevices().CloneNative())
+       if err != nil {
+               return err
+       }
+
+       // Get the volume name on storage.
+       volStorageName := project.Prefix(inst.Project(), inst.Name())
+
+       _, snapshotName, isSnap := 
shared.InstanceGetParentAndSnapshotName(src.Name())
+       if !isSnap {
+               return fmt.Errorf("Volume name must be a snapshot")
+       }
+
+       // Use the source snapshot's rootfs config (as this will later be 
restored into inst too).
+       vol := b.newVolume(volType, contentType, volStorageName, rootDiskConf)
+       err = b.driver.RestoreVolume(vol, snapshotName, op)
+       if err != nil {
+               return err
+       }
+
+       return nil
 }
 
 // MountInstanceSnapshot mounts an instance snapshot. It is mounted as read 
only so that the
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to