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

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) ===
Partially implements Create Image (for directory which is a no-op).

Other storage drivers will return ErrNotImplemented.
From 600825ac9a562005c128a66736c759111026f17a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 11:51:29 +0000
Subject: [PATCH 01/22] lxd/storage/volumes: Makes storagePoolVolumeTypePut
 logic consistent with storagePoolVolumeSnapshotTypePut

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

diff --git a/lxd/storage_volumes.go b/lxd/storage_volumes.go
index 0277b83c03..1f7f31cea4 100644
--- a/lxd/storage_volumes.go
+++ b/lxd/storage_volumes.go
@@ -976,9 +976,13 @@ func storagePoolVolumeTypePut(d *Daemon, r *http.Request, 
volumeTypeName string)
                        // means that modifying a snapshot's description gets 
routed here rather
                        // than the dedicated snapshot editing route. So need 
to handle snapshot
                        // volumes here too.
-                       err = d.cluster.StoragePoolVolumeUpdate(vol.Name, 
volumeType, poolID, req.Description, req.Config)
-                       if err != nil {
-                               return response.SmartError(err)
+
+                       // Update the database if description changed.
+                       if req.Description != vol.Description {
+                               err = 
d.cluster.StoragePoolVolumeUpdate(vol.Name, volumeType, poolID, 
req.Description, vol.Config)
+                               if err != nil {
+                                       response.SmartError(err)
+                               }
                        }
                }
        } else {

From 8375d6cdda473179a5d1145c7e463f6f8219d7ac Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 11:52:08 +0000
Subject: [PATCH 02/22] lxd/storage/volumes/snapshot: Moves
 storagePoolVolumeSnapshotTypePut DB logic

Moves DB logic from legacy storage functions into API directly (as just DB 
updates) as its just a description update.

This will then work with both old and new storage layers.

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

diff --git a/lxd/storage_volumes_snapshot.go b/lxd/storage_volumes_snapshot.go
index f38af7fef8..16794ab836 100644
--- a/lxd/storage_volumes_snapshot.go
+++ b/lxd/storage_volumes_snapshot.go
@@ -398,6 +398,7 @@ func storagePoolVolumeSnapshotTypeGet(d *Daemon, r 
*http.Request) response.Respo
        return response.SyncResponseETag(true, &snapshot, etag)
 }
 
+// storagePoolVolumeSnapshotTypePut allows a snapshot's description to be 
changed.
 func storagePoolVolumeSnapshotTypePut(d *Daemon, r *http.Request) 
response.Response {
        // Get the name of the storage pool the volume is supposed to be
        // attached to.
@@ -420,7 +421,7 @@ func storagePoolVolumeSnapshotTypePut(d *Daemon, r 
*http.Request) response.Respo
 
        // Check that the storage volume type is valid.
        if volumeType != storagePoolVolumeTypeCustom {
-               return response.BadRequest(fmt.Errorf("invalid storage volume 
type %s", volumeTypeName))
+               return response.BadRequest(fmt.Errorf("Invalid storage volume 
type %s", volumeTypeName))
        }
 
        resp := ForwardedResponseIfTargetIsRemote(d, r)
@@ -439,13 +440,13 @@ func storagePoolVolumeSnapshotTypePut(d *Daemon, r 
*http.Request) response.Respo
                return resp
        }
 
-       _, volume, err := 
d.cluster.StoragePoolNodeVolumeGetType(fullSnapshotName, volumeType, poolID)
+       _, vol, err := d.cluster.StoragePoolNodeVolumeGetType(fullSnapshotName, 
volumeType, poolID)
        if err != nil {
                return response.SmartError(err)
        }
 
        // Validate the ETag
-       etag := []interface{}{snapshotName, volume.Description, volume.Config}
+       etag := []interface{}{snapshotName, vol.Description, vol.Config}
        err = util.EtagCheck(r, etag)
        if err != nil {
                return response.PreconditionFailed(err)
@@ -457,22 +458,22 @@ func storagePoolVolumeSnapshotTypePut(d *Daemon, r 
*http.Request) response.Respo
                return response.BadRequest(err)
        }
 
-       var do func(*operations.Operation) error
-       var opDescription db.OperationType
-       do = func(op *operations.Operation) error {
-               err = storagePoolVolumeSnapshotUpdate(d.State(), poolName, 
volume.Name, volumeType, req.Description)
-               if err != nil {
-                       return err
+       do := func(op *operations.Operation) error {
+               // Update the database if description changed.
+               if req.Description != vol.Description {
+                       err = d.cluster.StoragePoolVolumeUpdate(vol.Name, 
volumeType, poolID, req.Description, vol.Config)
+                       if err != nil {
+                               return err
+                       }
                }
 
-               opDescription = db.OperationVolumeSnapshotDelete
                return nil
        }
 
        resources := map[string][]string{}
        resources["storage_volume_snapshots"] = []string{volumeName}
 
-       op, err := operations.OperationCreate(d.State(), "", 
operations.OperationClassTask, opDescription, resources, nil, do, nil, nil)
+       op, err := operations.OperationCreate(d.State(), "", 
operations.OperationClassTask, db.OperationSnapshotUpdate, resources, nil, do, 
nil, nil)
        if err != nil {
                return response.InternalError(err)
        }

From 441d1ad5bda2aeb4f370dd954b804938391d943e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 11:53:28 +0000
Subject: [PATCH 03/22] lxd/storage/volumes/utils: Removes unused
 storagePoolVolumeSnapshotUpdate

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage_volumes_utils.go | 22 ----------------------
 1 file changed, 22 deletions(-)

diff --git a/lxd/storage_volumes_utils.go b/lxd/storage_volumes_utils.go
index c70e8acb8a..ab7791e742 100644
--- a/lxd/storage_volumes_utils.go
+++ b/lxd/storage_volumes_utils.go
@@ -207,28 +207,6 @@ func storagePoolVolumeUpdate(state *state.State, poolName 
string, volumeName str
        return nil
 }
 
-func storagePoolVolumeSnapshotUpdate(state *state.State, poolName string, 
volumeName string, volumeType int, newDescription string) error {
-       s, err := storagePoolVolumeInit(state, "default", poolName, volumeName, 
volumeType)
-       if err != nil {
-               return err
-       }
-
-       oldWritable := s.GetStoragePoolVolumeWritable()
-       oldDescription := oldWritable.Description
-
-       poolID, err := state.Cluster.StoragePoolGetID(poolName)
-       if err != nil {
-               return err
-       }
-
-       // Update the database if something changed
-       if newDescription != oldDescription {
-               return state.Cluster.StoragePoolVolumeUpdate(volumeName, 
volumeType, poolID, newDescription, oldWritable.Config)
-       }
-
-       return nil
-}
-
 func storagePoolVolumeUsedByContainersGet(s *state.State, project, poolName 
string, volumeName string) ([]string, error) {
        insts, err := instanceLoadByProject(s, project)
        if err != nil {

From f524067312ef9617c79933745764bbc6e9c55ab9 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 13:24:31 +0000
Subject: [PATCH 04/22] lxd/storage/backend/lxd: Adds basic debug logging

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

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 5619577fb0..c88e0ddc31 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -15,6 +15,9 @@ import (
        "github.com/lxc/lxd/lxd/storage/memorypipe"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
+       log "github.com/lxc/lxd/shared/log15"
+       "github.com/lxc/lxd/shared/logger"
+       "github.com/lxc/lxd/shared/logging"
 )
 
 type lxdBackend struct {
@@ -22,6 +25,7 @@ type lxdBackend struct {
        id     int64
        name   string
        state  *state.State
+       logger logger.Logger
 }
 
 func (b *lxdBackend) DaemonState() *state.State {
@@ -51,6 +55,10 @@ func (b *lxdBackend) MigrationTypes(contentType 
drivers.ContentType) []migration
 
 // create creates the storage pool layout on the storage device.
 func (b *lxdBackend) create(dbPool *api.StoragePool, op *operations.Operation) 
error {
+       logger := logging.AddContext(b.logger, log.Ctx{"args": dbPool})
+       logger.Debug("create started")
+       defer logger.Debug("created finished")
+
        revertPath := true
 
        // Create the storage path.
@@ -103,11 +111,19 @@ func (b *lxdBackend) newVolume(volType 
drivers.VolumeType, contentType drivers.C
 }
 
 func (b *lxdBackend) GetResources() (*api.ResourcesStoragePool, error) {
+       logger := logging.AddContext(b.logger, nil)
+       logger.Debug("GetResources started")
+       defer logger.Debug("GetResources finished")
+
        return b.driver.GetResources()
 }
 
 // Delete removes the pool.
 func (b *lxdBackend) Delete(op *operations.Operation) error {
+       logger := logging.AddContext(b.logger, nil)
+       logger.Debug("Delete started")
+       defer logger.Debug("Delete finished")
+
        // Delete the low-level storage.
        err := b.driver.Delete(op)
        if err != nil {
@@ -126,11 +142,19 @@ func (b *lxdBackend) Delete(op *operations.Operation) 
error {
 
 // Mount mounts the storage pool.
 func (b *lxdBackend) Mount() (bool, error) {
+       logger := logging.AddContext(b.logger, nil)
+       logger.Debug("Mount started")
+       defer logger.Debug("Mount finished")
+
        return b.driver.Mount()
 }
 
 // Unmount unmounts the storage pool.
 func (b *lxdBackend) Unmount() (bool, error) {
+       logger := logging.AddContext(b.logger, nil)
+       logger.Debug("Unmount started")
+       defer logger.Debug("Unmount finished")
+
        return b.driver.Unmount()
 }
 
@@ -224,6 +248,10 @@ func (b *lxdBackend) CreateImage(img api.Image, op 
*operations.Operation) error
 
 // DeleteImage removes an image from the database and underlying storage 
device if needed.
 func (b *lxdBackend) DeleteImage(fingerprint string, op *operations.Operation) 
error {
+       logger := logging.AddContext(b.logger, log.Ctx{"fingerprint": 
fingerprint})
+       logger.Debug("DeleteImage started")
+       defer logger.Debug("DeleteImage finished")
+
        regexSHA256, err := regexp.Compile("^[0-9a-f]{64}$")
        if err != nil {
                return err
@@ -248,6 +276,10 @@ func (b *lxdBackend) DeleteImage(fingerprint string, op 
*operations.Operation) e
 
 // CreateCustomVolume creates an empty custom volume.
 func (b *lxdBackend) CreateCustomVolume(volName, desc string, config 
map[string]string, op *operations.Operation) error {
+       logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, 
"desc": desc, "config": config})
+       logger.Debug("CreateCustomVolume started")
+       defer logger.Debug("CreateCustomVolume finished")
+
        // Validate config.
        err := b.driver.ValidateVolume(b.newVolume(drivers.VolumeTypeCustom, 
drivers.ContentTypeFS, volName, config), false)
        if err != nil {
@@ -281,6 +313,10 @@ 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 {
+       logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, 
"desc": desc, "config": config, "srcPoolName": srcPoolName, "srcVolName": 
srcVolName, "srcVolOnly": srcVolOnly})
+       logger.Debug("CreateCustomVolumeFromCopy started")
+       defer logger.Debug("CreateCustomVolumeFromCopy finished")
+
        // Setup the source pool backend instance.
        var srcPool *lxdBackend
        if b.name == srcPoolName {
@@ -395,6 +431,10 @@ 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 {
+       logger := logging.AddContext(b.logger, log.Ctx{"volName": args.Name, 
"args": args})
+       logger.Debug("MigrateCustomVolume started")
+       defer logger.Debug("MigrateCustomVolume finished")
+
        vol := b.newVolume(drivers.VolumeTypeCustom, drivers.ContentTypeFS, 
args.Name, nil)
        err := b.driver.MigrateVolume(vol, conn, args, op)
        if err != nil {
@@ -406,6 +446,10 @@ 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 {
+       logger := logging.AddContext(b.logger, log.Ctx{"volName": args.Name, 
"args": args})
+       logger.Debug("CreateCustomVolumeFromMigration started")
+       defer logger.Debug("CreateCustomVolumeFromMigration finished")
+
        // Create slice to record DB volumes created if revert needed later.
        revertDBVolumes := []string{}
        defer func() {
@@ -455,6 +499,10 @@ func (b *lxdBackend) CreateCustomVolumeFromMigration(conn 
io.ReadWriteCloser, ar
 
 // RenameCustomVolume renames a custom volume and its snapshots.
 func (b *lxdBackend) RenameCustomVolume(volName string, newVolName string, op 
*operations.Operation) error {
+       logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, 
"newVolName": newVolName})
+       logger.Debug("RenameCustomVolume started")
+       defer logger.Debug("RenameCustomVolume finished")
+
        if shared.IsSnapshot(volName) {
                return fmt.Errorf("Volume name cannot be a snapshot")
        }
@@ -518,6 +566,10 @@ func (b *lxdBackend) RenameCustomVolume(volName string, 
newVolName string, op *o
 
 // UpdateCustomVolume applies the supplied config to the custom volume.
 func (b *lxdBackend) UpdateCustomVolume(volName, newDesc string, newConfig 
map[string]string, op *operations.Operation) error {
+       logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, 
"newDesc": newDesc, "newConfig": newConfig})
+       logger.Debug("UpdateCustomVolume started")
+       defer logger.Debug("UpdateCustomVolume finished")
+
        if shared.IsSnapshot(volName) {
                return fmt.Errorf("Volume name cannot be a snapshot")
        }
@@ -609,6 +661,10 @@ func (b *lxdBackend) UpdateCustomVolume(volName, newDesc 
string, newConfig map[s
 
 // DeleteCustomVolume removes a custom volume and its snapshots.
 func (b *lxdBackend) DeleteCustomVolume(volName string, op 
*operations.Operation) error {
+       logger := logging.AddContext(b.logger, log.Ctx{"volName": volName})
+       logger.Debug("DeleteCustomVolume started")
+       defer logger.Debug("DeleteCustomVolume finished")
+
        _, _, isSnap := shared.ContainerGetParentAndSnapshotName(volName)
        if isSnap {
                return fmt.Errorf("Volume name cannot be a snapshot")
@@ -667,16 +723,28 @@ func (b *lxdBackend) SetCustomVolumeQuota(vol 
api.StorageVolume, quota uint64) e
 
 // MountCustomVolume mounts a custom volume.
 func (b *lxdBackend) MountCustomVolume(volName string, op 
*operations.Operation) (bool, error) {
+       logger := logging.AddContext(b.logger, log.Ctx{"volName": volName})
+       logger.Debug("MountCustomVolume started")
+       defer logger.Debug("MountCustomVolume finished")
+
        return b.driver.MountVolume(drivers.VolumeTypeCustom, volName, op)
 }
 
 // UnmountCustomVolume unmounts a custom volume.
 func (b *lxdBackend) UnmountCustomVolume(volName string, op 
*operations.Operation) (bool, error) {
+       logger := logging.AddContext(b.logger, log.Ctx{"volName": volName})
+       logger.Debug("UnmountCustomVolume started")
+       defer logger.Debug("UnmountCustomVolume finished")
+
        return b.driver.UnmountVolume(drivers.VolumeTypeCustom, volName, op)
 }
 
 // CreateCustomVolumeSnapshot creates a snapshot of a custom volume.
 func (b *lxdBackend) CreateCustomVolumeSnapshot(volName string, 
newSnapshotName string, op *operations.Operation) error {
+       logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, 
"newSnapshotName": newSnapshotName})
+       logger.Debug("CreateCustomVolumeSnapshot started")
+       defer logger.Debug("CreateCustomVolumeSnapshot finished")
+
        if shared.IsSnapshot(volName) {
                return fmt.Errorf("Volume cannot be snapshot")
        }
@@ -732,6 +800,10 @@ func (b *lxdBackend) CreateCustomVolumeSnapshot(volName 
string, newSnapshotName
 
 // RenameCustomVolumeSnapshot renames a custom volume.
 func (b *lxdBackend) RenameCustomVolumeSnapshot(volName string, 
newSnapshotName string, op *operations.Operation) error {
+       logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, 
"newSnapshotName": newSnapshotName})
+       logger.Debug("RenameCustomVolumeSnapshot started")
+       defer logger.Debug("RenameCustomVolumeSnapshot finished")
+
        parentName, oldSnapshotName, isSnap := 
shared.ContainerGetParentAndSnapshotName(volName)
        if !isSnap {
                return fmt.Errorf("Volume name must be a snapshot")
@@ -759,6 +831,10 @@ func (b *lxdBackend) RenameCustomVolumeSnapshot(volName 
string, newSnapshotName
 
 // DeleteCustomVolumeSnapshot removes a custom volume snapshot.
 func (b *lxdBackend) DeleteCustomVolumeSnapshot(volName string, op 
*operations.Operation) error {
+       logger := logging.AddContext(b.logger, log.Ctx{"volName": volName})
+       logger.Debug("DeleteCustomVolumeSnapshot started")
+       defer logger.Debug("DeleteCustomVolumeSnapshot finished")
+
        parentName, snapName, isSnap := 
shared.ContainerGetParentAndSnapshotName(volName)
        if !isSnap {
                return fmt.Errorf("Volume name must be a snapshot")
@@ -781,6 +857,10 @@ func (b *lxdBackend) DeleteCustomVolumeSnapshot(volName 
string, op *operations.O
 
 // RestoreCustomVolume restores a custom volume from a snapshot.
 func (b *lxdBackend) RestoreCustomVolume(volName string, snapshotName string, 
op *operations.Operation) error {
+       logger := logging.AddContext(b.logger, log.Ctx{"volName": volName, 
"snapshotName": snapshotName})
+       logger.Debug("RestoreCustomVolume started")
+       defer logger.Debug("RestoreCustomVolume finished")
+
        if shared.IsSnapshot(volName) {
                return fmt.Errorf("Volume cannot be snapshot")
        }

From c08aada7660e7d72ba0bf93ebca596aa9d88e057 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 13:24:47 +0000
Subject: [PATCH 05/22] lxd/storage/backend/mock: Adds logger support

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

diff --git a/lxd/storage/backend_mock.go b/lxd/storage/backend_mock.go
index aa5f5f67f9..05aa1b9b4f 100644
--- a/lxd/storage/backend_mock.go
+++ b/lxd/storage/backend_mock.go
@@ -8,11 +8,13 @@ import (
        "github.com/lxc/lxd/lxd/state"
        "github.com/lxc/lxd/lxd/storage/drivers"
        "github.com/lxc/lxd/shared/api"
+       "github.com/lxc/lxd/shared/logger"
 )
 
 type mockBackend struct {
-       name  string
-       state *state.State
+       name   string
+       state  *state.State
+       logger logger.Logger
 }
 
 func (b *mockBackend) DaemonState() *state.State {

From e1a482df3cb1956d0a1f79b91d95e698f0f8de0f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 13:25:36 +0000
Subject: [PATCH 06/22] lxd/storage/load: Initialises logger

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

diff --git a/lxd/storage/load.go b/lxd/storage/load.go
index d25163f7fd..2c7298e4e7 100644
--- a/lxd/storage/load.go
+++ b/lxd/storage/load.go
@@ -8,6 +8,9 @@ import (
        "github.com/lxc/lxd/lxd/state"
        "github.com/lxc/lxd/lxd/storage/drivers"
        "github.com/lxc/lxd/shared/api"
+       log "github.com/lxc/lxd/shared/log15"
+       "github.com/lxc/lxd/shared/logger"
+       "github.com/lxc/lxd/shared/logging"
 )
 
 // MockBackend controls whether to run the storage logic in mock mode.
@@ -56,6 +59,7 @@ func CreatePool(state *state.State, poolID int64, dbPool 
*api.StoragePool, op *o
                pool := mockBackend{}
                pool.name = dbPool.Name
                pool.state = state
+               pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": 
"mock", "pool": pool.name})
                return &pool, nil
        }
 
@@ -71,6 +75,7 @@ func CreatePool(state *state.State, poolID int64, dbPool 
*api.StoragePool, op *o
        pool.id = poolID
        pool.name = dbPool.Name
        pool.state = state
+       pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": 
dbPool.Driver, "pool": pool.name})
 
        // Create the pool itself on the storage device..
        err = pool.create(dbPool, op)
@@ -88,6 +93,7 @@ func GetPoolByName(state *state.State, name string) (Pool, 
error) {
                pool := mockBackend{}
                pool.name = name
                pool.state = state
+               pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": 
"mock", "pool": pool.name})
                return &pool, nil
        }
 
@@ -114,6 +120,7 @@ func GetPoolByName(state *state.State, name string) (Pool, 
error) {
        pool.id = poolID
        pool.name = dbPool.Name
        pool.state = state
+       pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": 
dbPool.Driver, "pool": pool.name})
 
        return &pool, nil
 }

From 63a1244d0886cfc6fd0c2a90f81a15b356597c39 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 15:48:34 +0000
Subject: [PATCH 07/22] lxd/storage/drivers/driver/common: Adds driver logger
 with pool context

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_common.go | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/lxd/storage/drivers/driver_common.go 
b/lxd/storage/drivers/driver_common.go
index bf6dc8e158..6712aec86e 100644
--- a/lxd/storage/drivers/driver_common.go
+++ b/lxd/storage/drivers/driver_common.go
@@ -6,6 +6,7 @@ import (
 
        "github.com/lxc/lxd/lxd/migration"
        "github.com/lxc/lxd/lxd/state"
+       "github.com/lxc/lxd/shared/logger"
 )
 
 type common struct {
@@ -14,14 +15,16 @@ type common struct {
        getVolID       func(volType VolumeType, volName string) (int64, error)
        getCommonRules func() map[string]func(string) error
        state          *state.State
+       logger         logger.Logger
 }
 
-func (d *common) init(state *state.State, name string, config 
map[string]string, volIDFunc func(volType VolumeType, volName string) (int64, 
error), commonRulesFunc func() map[string]func(string) error) {
+func (d *common) init(state *state.State, name string, config 
map[string]string, logger logger.Logger, volIDFunc func(volType VolumeType, 
volName string) (int64, error), commonRulesFunc func() map[string]func(string) 
error) {
        d.name = name
        d.config = config
        d.getVolID = volIDFunc
        d.getCommonRules = commonRulesFunc
        d.state = state
+       d.logger = logger
 }
 
 // validateVolume validates a volume config against common rules and optional 
driver specific rules.

From 0724ac3f79933834040ddd4a2794742ff1057eae Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 15:48:54 +0000
Subject: [PATCH 08/22] lxd/storage/drivers/interface: Updates with pool
 context logger

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

diff --git a/lxd/storage/drivers/interface.go b/lxd/storage/drivers/interface.go
index 09710b17ef..f98b634586 100644
--- a/lxd/storage/drivers/interface.go
+++ b/lxd/storage/drivers/interface.go
@@ -7,13 +7,14 @@ import (
        "github.com/lxc/lxd/lxd/operations"
        "github.com/lxc/lxd/lxd/state"
        "github.com/lxc/lxd/shared/api"
+       "github.com/lxc/lxd/shared/logger"
 )
 
 // driver is the extended internal interface.
 type driver interface {
        Driver
 
-       init(state *state.State, name string, config map[string]string, 
volIDFunc func(volType VolumeType, volName string) (int64, error), 
commonRulesFunc func() map[string]func(string) error)
+       init(state *state.State, name string, config map[string]string, logger 
logger.Logger, volIDFunc func(volType VolumeType, volName string) (int64, 
error), commonRulesFunc func() map[string]func(string) error)
 }
 
 // Driver represents a low-level storage driver.

From 2f1737528f8e891d265e0a4622525a6fa09b1e92 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 15:49:18 +0000
Subject: [PATCH 09/22] lxd/storage/utils: Updates VolumeValidateConfig to use
 update driver loader

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

diff --git a/lxd/storage/utils.go b/lxd/storage/utils.go
index acc5e6069c..b22e8c1ada 100644
--- a/lxd/storage/utils.go
+++ b/lxd/storage/utils.go
@@ -526,7 +526,7 @@ var StorageVolumeConfigKeys = map[string]func(value string) 
([]string, error){
 // VolumeValidateConfig validations volume config.
 func VolumeValidateConfig(name string, config map[string]string, parentPool 
*api.StoragePool) error {
        // Validate volume config using the new driver interface if supported.
-       driver, err := drivers.Load(nil, parentPool.Driver, parentPool.Name, 
parentPool.Config, nil, validateVolumeCommonRules)
+       driver, err := drivers.Load(nil, parentPool.Driver, parentPool.Name, 
parentPool.Config, nil, nil, validateVolumeCommonRules)
        if err != drivers.ErrUnknownDriver {
                // Note: This legacy validation function doesn't have the 
concept of validating
                // different volumes types, so the types are hard coded as 
Custom and FS.

From 01e5b3d84dfa84064a0a0cfb9907334a91d26ea2 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 15:49:44 +0000
Subject: [PATCH 10/22] lxd/storage/load: Updates loaders to support contextual
 loggers

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

diff --git a/lxd/storage/load.go b/lxd/storage/load.go
index 2c7298e4e7..1c134d75d6 100644
--- a/lxd/storage/load.go
+++ b/lxd/storage/load.go
@@ -63,8 +63,10 @@ func CreatePool(state *state.State, poolID int64, dbPool 
*api.StoragePool, op *o
                return &pool, nil
        }
 
+       logger := logging.AddContext(logger.Log, log.Ctx{"driver": 
dbPool.Driver, "pool": dbPool.Name})
+
        // Load the storage driver.
-       driver, err := drivers.Load(state, dbPool.Driver, dbPool.Name, 
dbPool.Config, volIDFuncMake(state, poolID), validateVolumeCommonRules)
+       driver, err := drivers.Load(state, dbPool.Driver, dbPool.Name, 
dbPool.Config, logger, volIDFuncMake(state, poolID), validateVolumeCommonRules)
        if err != nil {
                return nil, err
        }
@@ -75,7 +77,7 @@ func CreatePool(state *state.State, poolID int64, dbPool 
*api.StoragePool, op *o
        pool.id = poolID
        pool.name = dbPool.Name
        pool.state = state
-       pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": 
dbPool.Driver, "pool": pool.name})
+       pool.logger = logger
 
        // Create the pool itself on the storage device..
        err = pool.create(dbPool, op)
@@ -108,8 +110,10 @@ func GetPoolByName(state *state.State, name string) (Pool, 
error) {
                dbPool.Config = map[string]string{}
        }
 
+       logger := logging.AddContext(logger.Log, log.Ctx{"driver": 
dbPool.Driver, "pool": dbPool.Name})
+
        // Load the storage driver.
-       driver, err := drivers.Load(state, dbPool.Driver, dbPool.Name, 
dbPool.Config, volIDFuncMake(state, poolID), validateVolumeCommonRules)
+       driver, err := drivers.Load(state, dbPool.Driver, dbPool.Name, 
dbPool.Config, logger, volIDFuncMake(state, poolID), validateVolumeCommonRules)
        if err != nil {
                return nil, err
        }
@@ -120,7 +124,7 @@ func GetPoolByName(state *state.State, name string) (Pool, 
error) {
        pool.id = poolID
        pool.name = dbPool.Name
        pool.state = state
-       pool.logger = logging.AddContext(logger.Log, log.Ctx{"driver": 
dbPool.Driver, "pool": pool.name})
+       pool.logger = logger
 
        return &pool, nil
 }

From 4ef30c990afdcdcd13b1e65bd671357051aafc5f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 15:50:03 +0000
Subject: [PATCH 11/22] lxd/storage/drivers/load: Updates loaders to support
 contextual loggers

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

diff --git a/lxd/storage/drivers/load.go b/lxd/storage/drivers/load.go
index a10fdfd01f..17ca227f7b 100644
--- a/lxd/storage/drivers/load.go
+++ b/lxd/storage/drivers/load.go
@@ -2,6 +2,7 @@ package drivers
 
 import (
        "github.com/lxc/lxd/lxd/state"
+       "github.com/lxc/lxd/shared/logger"
 )
 
 var drivers = map[string]func() driver{
@@ -9,7 +10,7 @@ var drivers = map[string]func() driver{
 }
 
 // Load returns a Driver for an existing low-level storage pool.
-func Load(state *state.State, driverName string, name string, config 
map[string]string, volIDFunc func(volType VolumeType, volName string) (int64, 
error), commonRulesFunc func() map[string]func(string) error) (Driver, error) {
+func Load(state *state.State, driverName string, name string, config 
map[string]string, logger logger.Logger, volIDFunc func(volType VolumeType, 
volName string) (int64, error), commonRulesFunc func() map[string]func(string) 
error) (Driver, error) {
        // Locate the driver loader.
        driverFunc, ok := drivers[driverName]
        if !ok {
@@ -17,7 +18,7 @@ func Load(state *state.State, driverName string, name string, 
config map[string]
        }
 
        d := driverFunc()
-       d.init(state, name, config, volIDFunc, commonRulesFunc)
+       d.init(state, name, config, logger, volIDFunc, commonRulesFunc)
 
        return d, nil
 }
@@ -38,7 +39,7 @@ func SupportedDrivers() []Info {
        supportedDrivers := []Info{}
 
        for driverName := range drivers {
-               driver, err := Load(nil, driverName, "", nil, nil, nil)
+               driver, err := Load(nil, driverName, "", nil, nil, nil, nil)
                if err != nil {
                        continue
                }

From 186b2606d298baee35bdc5994d5a9b5730a9cef9 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 16:38:45 +0000
Subject: [PATCH 12/22] container/lxc: Hooks up root device usage to new
 storage package

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

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 2f0b0200aa..8dc40f7292 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -41,7 +41,8 @@ import (
        "github.com/lxc/lxd/lxd/project"
        "github.com/lxc/lxd/lxd/seccomp"
        "github.com/lxc/lxd/lxd/state"
-       driver "github.com/lxc/lxd/lxd/storage"
+       storagePools "github.com/lxc/lxd/lxd/storage"
+       storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
        "github.com/lxc/lxd/lxd/template"
        "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
@@ -324,7 +325,7 @@ func containerLXCCreate(s *state.State, args 
db.InstanceArgs) (container, error)
 
        // Fill in any default volume config
        volumeConfig := map[string]string{}
-       err = driver.VolumeFillDefault(storagePool, volumeConfig, pool)
+       err = storagePools.VolumeFillDefault(storagePool, volumeConfig, pool)
        if err != nil {
                c.Delete()
                return nil, err
@@ -3580,7 +3581,7 @@ func (c *containerLXC) Delete() error {
                // Delete the container from disk
                if c.storage != nil && !isImport {
                        _, poolName, _ := c.storage.GetContainerPoolInfo()
-                       containerMountPoint := 
driver.GetContainerMountPoint(c.Project(), poolName, c.Name())
+                       containerMountPoint := 
storagePools.GetContainerMountPoint(c.Project(), poolName, c.Name())
                        if shared.PathExists(c.Path()) ||
                                shared.PathExists(containerMountPoint) {
                                err := c.storage.ContainerDelete(c)
@@ -5904,9 +5905,26 @@ func (c *containerLXC) diskState() 
map[string]api.InstanceStateDisk {
                        continue
                }
 
-               usage, err := c.storage.ContainerGetUsage(c)
-               if err != nil {
-                       continue
+               var usage int64
+
+               // Check if we can load new storage layer for pool driver type.
+               pool, err := storagePools.GetPoolByName(c.state, 
dev.Config["pool"])
+               if err != storageDrivers.ErrUnknownDriver {
+                       if err != nil {
+                               logger.Errorf("Error loading storage pool for 
%s: %v", c.Name(), err)
+                               continue
+                       }
+
+                       usage, err = pool.GetInstanceUsage(c)
+                       if err != nil {
+                               logger.Errorf("Error getting disk usage for %s: 
%v", c.Name(), err)
+                               continue
+                       }
+               } else {
+                       usage, err = c.storage.ContainerGetUsage(c)
+                       if err != nil {
+                               continue
+                       }
                }
 
                disk[dev.Name] = api.InstanceStateDisk{Usage: usage}
@@ -6718,7 +6736,7 @@ func (c *containerLXC) State() string {
 // Various container paths
 func (c *containerLXC) Path() string {
        name := project.Prefix(c.Project(), c.Name())
-       return driver.ContainerPath(name, c.IsSnapshot())
+       return storagePools.ContainerPath(name, c.IsSnapshot())
 }
 
 func (c *containerLXC) DevicesPath() string {

From 8490022477076fa5efe22579cae74d367b38ef25 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 16:39:45 +0000
Subject: [PATCH 13/22] lxd/storage/backend/lxd: Updates name of instance arg
 to inst from i

For clarity we don't use i to mean instance.

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

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index c88e0ddc31..60fb8c7bf4 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -158,43 +158,43 @@ func (b *lxdBackend) Unmount() (bool, error) {
        return b.driver.Unmount()
 }
 
-func (b *lxdBackend) CreateInstance(i Instance, op *operations.Operation) 
error {
+func (b *lxdBackend) CreateInstance(inst Instance, op *operations.Operation) 
error {
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) CreateInstanceFromBackup(i Instance, sourcePath string, 
op *operations.Operation) error {
+func (b *lxdBackend) CreateInstanceFromBackup(inst Instance, sourcePath 
string, op *operations.Operation) error {
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) CreateInstanceFromCopy(i Instance, src Instance, 
snapshots bool, op *operations.Operation) error {
+func (b *lxdBackend) CreateInstanceFromCopy(inst Instance, src Instance, 
snapshots bool, op *operations.Operation) error {
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) CreateInstanceFromImage(i Instance, fingerprint string, 
op *operations.Operation) error {
+func (b *lxdBackend) CreateInstanceFromImage(inst Instance, fingerprint 
string, op *operations.Operation) error {
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) CreateInstanceFromMigration(i Instance, conn 
io.ReadWriteCloser, args migration.SinkArgs, op *operations.Operation) error {
+func (b *lxdBackend) CreateInstanceFromMigration(inst Instance, conn 
io.ReadWriteCloser, args migration.SinkArgs, op *operations.Operation) error {
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) RenameInstance(i Instance, newName string, op 
*operations.Operation) error {
+func (b *lxdBackend) RenameInstance(inst Instance, newName string, op 
*operations.Operation) error {
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) DeleteInstance(i Instance, op *operations.Operation) 
error {
+func (b *lxdBackend) DeleteInstance(inst Instance, op *operations.Operation) 
error {
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) MigrateInstance(i Instance, snapshots bool, args 
migration.SourceArgs) (migration.StorageSourceDriver, error) {
+func (b *lxdBackend) MigrateInstance(inst Instance, snapshots bool, args 
migration.SourceArgs) (migration.StorageSourceDriver, error) {
        return nil, ErrNotImplemented
 }
 
-func (b *lxdBackend) RefreshInstance(i Instance, src Instance, snapshots bool, 
op *operations.Operation) error {
+func (b *lxdBackend) RefreshInstance(inst Instance, src Instance, snapshots 
bool, op *operations.Operation) error {
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) BackupInstance(i Instance, targetPath string, optimized 
bool, snapshots bool, op *operations.Operation) error {
+func (b *lxdBackend) BackupInstance(inst Instance, targetPath string, 
optimized bool, snapshots bool, op *operations.Operation) error {
        return ErrNotImplemented
 }
 
@@ -202,43 +202,43 @@ func (b *lxdBackend) GetInstanceUsage(i Instance) 
(uint64, error) {
        return 0, ErrNotImplemented
 }
 
-func (b *lxdBackend) SetInstanceQuota(i Instance, quota uint64) error {
+func (b *lxdBackend) SetInstanceQuota(inst Instance, quota uint64) error {
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) MountInstance(i Instance) (bool, error) {
+func (b *lxdBackend) MountInstance(inst Instance) (bool, error) {
        return true, ErrNotImplemented
 }
 
-func (b *lxdBackend) UnmountInstance(i Instance) (bool, error) {
+func (b *lxdBackend) UnmountInstance(inst Instance) (bool, error) {
        return true, ErrNotImplemented
 }
 
-func (b *lxdBackend) GetInstanceDisk(i Instance) (string, string, error) {
+func (b *lxdBackend) GetInstanceDisk(inst Instance) (string, string, error) {
        return "", "", ErrNotImplemented
 }
 
-func (b *lxdBackend) CreateInstanceSnapshot(i Instance, name string, op 
*operations.Operation) error {
+func (b *lxdBackend) CreateInstanceSnapshot(inst Instance, name string, op 
*operations.Operation) error {
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) RenameInstanceSnapshot(i Instance, newName string, op 
*operations.Operation) error {
+func (b *lxdBackend) RenameInstanceSnapshot(inst Instance, newName string, op 
*operations.Operation) error {
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) DeleteInstanceSnapshot(i Instance, op 
*operations.Operation) error {
+func (b *lxdBackend) DeleteInstanceSnapshot(inst Instance, op 
*operations.Operation) error {
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) RestoreInstanceSnapshot(i Instance, op 
*operations.Operation) error {
+func (b *lxdBackend) RestoreInstanceSnapshot(inst Instance, op 
*operations.Operation) error {
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) MountInstanceSnapshot(i Instance) (bool, error) {
+func (b *lxdBackend) MountInstanceSnapshot(inst Instance) (bool, error) {
        return true, ErrNotImplemented
 }
 
-func (b *lxdBackend) UnmountInstanceSnapshot(i Instance) (bool, error) {
+func (b *lxdBackend) UnmountInstanceSnapshot(inst Instance) (bool, error) {
        return true, ErrNotImplemented
 }
 

From 0a8db6591970e4b5282a4c2c68f7db2fbfce6543 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 16:40:18 +0000
Subject: [PATCH 14/22] lxd/storage/backend/lxd: Implements GetInstanceUsage

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

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 60fb8c7bf4..1b8d2c0ad5 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -8,6 +8,7 @@ import (
        "strings"
 
        "github.com/lxc/lxd/lxd/db"
+       "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"
@@ -198,8 +199,17 @@ func (b *lxdBackend) BackupInstance(inst Instance, 
targetPath string, optimized
        return ErrNotImplemented
 }
 
-func (b *lxdBackend) GetInstanceUsage(i Instance) (uint64, error) {
-       return 0, ErrNotImplemented
+// GetInstanceUsage returns the disk usage of the Instance's root device.
+func (b *lxdBackend) GetInstanceUsage(inst Instance) (int64, error) {
+       logger := logging.AddContext(b.logger, log.Ctx{"instance": inst.Name()})
+       logger.Debug("GetInstanceUsage started")
+       defer logger.Debug("GetInstanceUsage finished")
+
+       if inst.Type() == instancetype.Container {
+               return b.driver.GetVolumeUsage(drivers.VolumeTypeContainer, 
inst.Name())
+       }
+
+       return -1, ErrNotImplemented
 }
 
 func (b *lxdBackend) SetInstanceQuota(inst Instance, quota uint64) error {
@@ -712,13 +722,9 @@ func (b *lxdBackend) DeleteCustomVolume(volName string, op 
*operations.Operation
        return nil
 }
 
-func (b *lxdBackend) GetCustomVolumeUsage(vol api.StorageVolume) (uint64, 
error) {
-       return 0, ErrNotImplemented
-}
-
-// SetCustomVolumeQuota modifies the custom volume's quota.
-func (b *lxdBackend) SetCustomVolumeQuota(vol api.StorageVolume, quota uint64) 
error {
-       return ErrNotImplemented
+// GetCustomVolumeUsage returns the disk space used by the custom volume.
+func (b *lxdBackend) GetCustomVolumeUsage(volName string) (int64, error) {
+       return b.driver.GetVolumeUsage(drivers.VolumeTypeCustom, volName)
 }
 
 // MountCustomVolume mounts a custom volume.

From 563b047a22b5f556354027ccd34b1514f3f9cb25 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 16:40:54 +0000
Subject: [PATCH 15/22] lxd/storage/backend/mock: Changes GetInstanceUsage
 signature

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

diff --git a/lxd/storage/backend_mock.go b/lxd/storage/backend_mock.go
index 05aa1b9b4f..6770735c8e 100644
--- a/lxd/storage/backend_mock.go
+++ b/lxd/storage/backend_mock.go
@@ -98,7 +98,7 @@ func (b *mockBackend) BackupInstance(i Instance, targetPath 
string, optimized bo
        return nil
 }
 
-func (b *mockBackend) GetInstanceUsage(i Instance) (uint64, error) {
+func (b *mockBackend) GetInstanceUsage(i Instance) (int64, error) {
        return 0, nil
 }
 
@@ -178,14 +178,10 @@ func (b *mockBackend) 
CreateCustomVolumeFromMigration(conn io.ReadWriteCloser, a
        return nil
 }
 
-func (b *mockBackend) GetCustomVolumeUsage(vol api.StorageVolume) (uint64, 
error) {
+func (b *mockBackend) GetCustomVolumeUsage(volName string) (int64, error) {
        return 0, nil
 }
 
-func (b *mockBackend) SetCustomVolumeQuota(vol api.StorageVolume, quota 
uint64) error {
-       return nil
-}
-
 func (b *mockBackend) MountCustomVolume(volName string, op 
*operations.Operation) (bool, error) {
        return true, nil
 }

From c0aeb63175ca37a9a1938339f3d2c891cf63f4dd Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 16:41:22 +0000
Subject: [PATCH 16/22] lxd/storage/drivers/driver/dir: Implements
 GetVolumeUsage

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_dir.go | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/lxd/storage/drivers/driver_dir.go 
b/lxd/storage/drivers/driver_dir.go
index 34af147f26..bafb1fb06f 100644
--- a/lxd/storage/drivers/driver_dir.go
+++ b/lxd/storage/drivers/driver_dir.go
@@ -119,6 +119,31 @@ func (d *dir) GetResources() (*api.ResourcesStoragePool, 
error) {
        return vfsResources(GetPoolMountPath(d.name))
 }
 
+// GetVolumeUsage returns the disk space used by the volume.
+func (d *dir) GetVolumeUsage(volType VolumeType, volName string) (int64, 
error) {
+       volPath := GetVolumeMountPath(d.name, volType, volName)
+       ok, err := quota.Supported(volPath)
+       if err != nil || !ok {
+               return -1, fmt.Errorf("The backing filesystem doesn't support 
quotas")
+       }
+
+       // Get the volume ID for the volume to access quota.
+       volID, err := d.getVolID(volType, volName)
+       if err != nil {
+               return -1, err
+       }
+
+       projectID := d.quotaProjectID(volID)
+
+       // Get project quota used.
+       size, err := quota.GetProjectUsage(volPath, projectID)
+       if err != nil {
+               return -1, err
+       }
+
+       return size, nil
+}
+
 // ValidateVolume validates the supplied volume config.
 func (d *dir) ValidateVolume(vol Volume, removeUnknownKeys bool) error {
        return d.validateVolume(vol, nil, removeUnknownKeys)

From 8eba4831a53bec9c23edacf09c23bd62c9866edf Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 16:41:42 +0000
Subject: [PATCH 17/22] lxd/storage/drivers/interface: Adds GetVolumeUsage

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

diff --git a/lxd/storage/drivers/interface.go b/lxd/storage/drivers/interface.go
index f98b634586..50bab56cb3 100644
--- a/lxd/storage/drivers/interface.go
+++ b/lxd/storage/drivers/interface.go
@@ -37,6 +37,7 @@ type Driver interface {
        DeleteVolume(volType VolumeType, volName string, op 
*operations.Operation) error
        RenameVolume(volType VolumeType, volName string, newName string, op 
*operations.Operation) error
        UpdateVolume(vol Volume, changedConfig map[string]string) error
+       GetVolumeUsage(volType VolumeType, volName string) (int64, error)
 
        // MountVolume mounts a storage volume, returns true if we caused a new 
mount, false if
        // already mounted.

From f3e2a461d9210c5af086d510a05a1ad3db962d92 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 16:42:01 +0000
Subject: [PATCH 18/22] lxd/storage/interfaces: Changes GetInstanceUsage
 signature

 Removes Snapshots from Instance interface for now as causing issues when used 
from main package.

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/interfaces.go | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/lxd/storage/interfaces.go b/lxd/storage/interfaces.go
index 45f5e22b25..49a4ea02ce 100644
--- a/lxd/storage/interfaces.go
+++ b/lxd/storage/interfaces.go
@@ -19,7 +19,6 @@ type Instance interface {
        Path() string
 
        IsRunning() bool
-       Snapshots() ([]Instance, error)
        TemplateApply(trigger string) error
 }
 
@@ -52,7 +51,7 @@ type Pool interface {
        RefreshInstance(i Instance, src Instance, snapshots bool, op 
*operations.Operation) error
        BackupInstance(i Instance, targetPath string, optimized bool, snapshots 
bool, op *operations.Operation) error
 
-       GetInstanceUsage(i Instance) (uint64, error)
+       GetInstanceUsage(i Instance) (int64, error)
        SetInstanceQuota(i Instance, quota uint64) error
 
        MountInstance(i Instance) (bool, error)
@@ -77,7 +76,7 @@ type Pool interface {
        UpdateCustomVolume(volName, newDesc string, newConfig 
map[string]string, op *operations.Operation) error
        RenameCustomVolume(volName string, newVolName string, op 
*operations.Operation) error
        DeleteCustomVolume(volName string, op *operations.Operation) error
-       GetCustomVolumeUsage(vol api.StorageVolume) (uint64, error)
+       GetCustomVolumeUsage(volName string) (int64, error)
        MountCustomVolume(volName string, op *operations.Operation) (bool, 
error)
        UnmountCustomVolume(volName string, op *operations.Operation) (bool, 
error)
 

From 86470aa6a0c4c9f285a337f8882c696a7dccf19f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 17:54:00 +0000
Subject: [PATCH 19/22] lxd/images: Links imageCreateInPool to new storage
 package

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

diff --git a/lxd/images.go b/lxd/images.go
index 67b95e67b4..77b543cd06 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -33,6 +33,8 @@ import (
        "github.com/lxc/lxd/lxd/operations"
        "github.com/lxc/lxd/lxd/response"
        "github.com/lxc/lxd/lxd/state"
+       storagePools "github.com/lxc/lxd/lxd/storage"
+       storageDrivers "github.com/lxc/lxd/lxd/storage/drivers"
        "github.com/lxc/lxd/lxd/task"
        "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
@@ -626,17 +628,31 @@ func imageCreateInPool(d *Daemon, info *api.Image, 
storagePool string) error {
                return fmt.Errorf("No storage pool specified")
        }
 
-       // Initialize a new storage interface.
-       s, err := storagePoolInit(d.State(), storagePool)
-       if err != nil {
-               return err
-       }
+       // Check if we can load new storage layer for pool driver type.
+       pool, err := storagePools.GetPoolByName(d.State(), storagePool)
+       if err != storageDrivers.ErrUnknownDriver {
+               if err != nil {
+                       return err
+               }
+
+               err = pool.CreateImage(info.Fingerprint, nil)
+               if err != nil {
+                       return err
+               }
+       } else {
+               // Initialize a new storage interface.
+               s, err := storagePoolInit(d.State(), storagePool)
+               if err != nil {
+                       return err
+               }
+
+               // Create the storage volume for the image on the requested 
storage
+               // pool.
+               err = s.ImageCreate(info.Fingerprint, nil)
+               if err != nil {
+                       return err
+               }
 
-       // Create the storage volume for the image on the requested storage
-       // pool.
-       err = s.ImageCreate(info.Fingerprint, nil)
-       if err != nil {
-               return err
        }
 
        return nil
@@ -1084,6 +1100,7 @@ func autoUpdateImage(d *Daemon, op *operations.Operation, 
id int, info *api.Imag
 
        // Update the image on each pool where it currently exists.
        hash := fingerprint
+
        for _, poolName := range poolNames {
                newInfo, err := d.ImageDownload(op, source.Server, 
source.Protocol, source.Certificate, "", source.Alias, info.Type, false, true, 
poolName, false, project)
 

From ef6bfab7b2be3a4e8ab858f07199f5823d1f7e75 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 17:54:18 +0000
Subject: [PATCH 20/22] lxd/storage/backend/lxd: Implements CreateImage

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

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 1b8d2c0ad5..3a51642a92 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -252,7 +252,17 @@ func (b *lxdBackend) UnmountInstanceSnapshot(inst 
Instance) (bool, error) {
        return true, ErrNotImplemented
 }
 
-func (b *lxdBackend) CreateImage(img api.Image, op *operations.Operation) 
error {
+// CreateImage creates an optimized volume of the image if supported by the 
storage pool driver.
+func (b *lxdBackend) CreateImage(fingerprint string, op *operations.Operation) 
error {
+       logger := logging.AddContext(b.logger, log.Ctx{"fingerprint": 
fingerprint})
+       logger.Debug("CreateImage started")
+       defer logger.Debug("CreateImage finished")
+
+       if !b.driver.Info().OptimizedImages {
+               return nil // Nothing to do for drivers that don't support 
optimized images volumes.
+       }
+
+       // TODO volume creation with a filler function to populate 
volume/snapshot with image.
        return ErrNotImplemented
 }
 

From 68b7d0c8b5feefef67c52b85ed49b1453e53e230 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 17:54:38 +0000
Subject: [PATCH 21/22] lxd/storage/backend/mock: Updates CreateImage
 definition

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 6770735c8e..5cbab80ec3 100644
--- a/lxd/storage/backend_mock.go
+++ b/lxd/storage/backend_mock.go
@@ -142,7 +142,7 @@ func (b *mockBackend) UnmountInstanceSnapshot(i Instance) 
(bool, error) {
        return true, nil
 }
 
-func (b *mockBackend) CreateImage(img api.Image, op *operations.Operation) 
error {
+func (b *mockBackend) CreateImage(fingerprint string, op 
*operations.Operation) error {
        return nil
 }
 

From f62b64dc3b032ee90b97bcd84accf7378deb512c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Thu, 31 Oct 2019 17:54:56 +0000
Subject: [PATCH 22/22] lxd/storage/interfaces: Updates CreateImage definition

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

diff --git a/lxd/storage/interfaces.go b/lxd/storage/interfaces.go
index 49a4ea02ce..d8853c0096 100644
--- a/lxd/storage/interfaces.go
+++ b/lxd/storage/interfaces.go
@@ -67,7 +67,7 @@ type Pool interface {
        UnmountInstanceSnapshot(i Instance) (bool, error)
 
        // Images.
-       CreateImage(img api.Image, op *operations.Operation) error
+       CreateImage(fingerprint string, op *operations.Operation) error
        DeleteImage(fingerprint string, op *operations.Operation) error
 
        // Custom volumes.
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to