[lxc-devel] [lxd/master] Storage update validation

tomponline on Github lxc-bot at linuxcontainers.org
Fri Dec 13 17:24:31 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 589 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191213/04ea3991/attachment-0001.bin>
-------------- next part --------------
From 71e5e4424b0cc4d4308408303fff2739653f305c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 15:35:37 +0000
Subject: [PATCH 01/12] lxd/storage: Removes unnecessary argument in
 backendLXD.create()

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/backend_lxd.go | 4 ++--
 lxd/storage/load.go        | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 4d042f7fe5..f419d785ab 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -59,8 +59,8 @@ func (b *lxdBackend) MigrationTypes(contentType drivers.ContentType, refresh boo
 
 // create creates the storage pool layout on the storage device.
 // localOnly is used for clustering where only a single node should do remote storage setup.
-func (b *lxdBackend) create(dbPool *api.StoragePoolsPost, localOnly bool, op *operations.Operation) error {
-	logger := logging.AddContext(b.logger, log.Ctx{"args": dbPool})
+func (b *lxdBackend) create(localOnly bool, op *operations.Operation) error {
+	logger := logging.AddContext(b.logger, log.Ctx{"config": b.db.Config, "description": b.db.Description, "localOnly": localOnly})
 	logger.Debug("create started")
 	defer logger.Debug("created finished")
 
diff --git a/lxd/storage/load.go b/lxd/storage/load.go
index f89304c649..6a0986c03d 100644
--- a/lxd/storage/load.go
+++ b/lxd/storage/load.go
@@ -104,7 +104,7 @@ func CreatePool(state *state.State, poolID int64, dbPool *api.StoragePoolsPost,
 	pool.logger = logger
 
 	// Create the pool itself on the storage device..
-	err = pool.create(dbPool, localOnly, op)
+	err = pool.create(localOnly, op)
 	if err != nil {
 		return nil, err
 	}

From 7d6af06d85734d43eaa7376e4ab5b0ca41c28e7d Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 17:13:35 +0000
Subject: [PATCH 02/12] lxd/storage/backend/lxd: Comment on function
 description

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/backend_lxd.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index f419d785ab..7f2b5ddbf7 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -120,6 +120,7 @@ func (b *lxdBackend) newVolume(volType drivers.VolumeType, contentType drivers.C
 	return drivers.NewVolume(b.driver, b.name, volType, contentType, volName, volConfig)
 }
 
+// GetResources returns utilisation information about the pool.
 func (b *lxdBackend) GetResources() (*api.ResourcesStoragePool, error) {
 	logger := logging.AddContext(b.logger, nil)
 	logger.Debug("GetResources started")

From 86ffcb4ff63a83737bf6f14f08e5a1414f709a0b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 17:13:54 +0000
Subject: [PATCH 03/12] lxd/storage/backend/lxd: Implements UpdateInstance

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

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 7f2b5ddbf7..535329cc9b 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -1147,6 +1147,70 @@ func (b *lxdBackend) DeleteInstance(inst instance.Instance, op *operations.Opera
 	return nil
 }
 
+// UpdateInstance updates an instance volume's config.
+func (b *lxdBackend) UpdateInstance(inst instance.Instance, newDesc string, newConfig map[string]string, op *operations.Operation) error {
+	logger := logging.AddContext(b.logger, log.Ctx{"project": inst.Project(), "instance": inst.Name(), "newDesc": newDesc, "newConfig": newConfig})
+	logger.Debug("UpdateInstance started")
+	defer logger.Debug("UpdateInstance finished")
+
+	if inst.IsSnapshot() {
+		return fmt.Errorf("Instance cannot be a snapshot")
+	}
+
+	// Check we can convert the instance to the volume types needed.
+	volType, err := InstanceTypeToVolumeType(inst.Type())
+	if err != nil {
+		return err
+	}
+
+	volDBType, err := VolumeTypeToDBType(volType)
+	if err != nil {
+		return err
+	}
+
+	volStorageName := project.Prefix(inst.Project(), inst.Name())
+	contentType := InstanceContentType(inst)
+
+	// Validate config.
+	newVol := b.newVolume(volType, contentType, volStorageName, newConfig)
+	err = b.driver.ValidateVolume(newVol, false)
+	if err != nil {
+		return err
+	}
+
+	// Get current config to compare what has changed.
+	_, curVol, err := b.state.Cluster.StoragePoolNodeVolumeGetTypeByProject(inst.Project(), volStorageName, volDBType, b.ID())
+	if err != nil {
+		if err == db.ErrNoSuchObject {
+			return fmt.Errorf("Volume doesn't exist")
+		}
+
+		return err
+	}
+
+	// Apply config changes if there are any.
+	changedConfig, userOnly := b.detectChangedConfig(curVol.Config, newConfig)
+	if len(changedConfig) != 0 {
+		curVol := b.newVolume(volType, contentType, volStorageName, curVol.Config)
+		if !userOnly {
+			err = b.driver.UpdateVolume(curVol, changedConfig)
+			if err != nil {
+				return err
+			}
+		}
+	}
+
+	// Update the database if something changed.
+	if len(changedConfig) != 0 || newDesc != curVol.Description {
+		err = b.state.Cluster.StoragePoolVolumeUpdateByProject(inst.Project(), volStorageName, volDBType, b.ID(), newDesc, newConfig)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // 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.Instance, conn io.ReadWriteCloser, args migration.VolumeSourceArgs, op *operations.Operation) error {

From e96db0a7f9643e4a7ae5a506e3bb18a56b53920e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 17:14:09 +0000
Subject: [PATCH 04/12] lxd/storage/backend/lxd: Implements UpdateImage

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

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 535329cc9b..76a123bc60 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -1798,6 +1798,15 @@ func (b *lxdBackend) DeleteImage(fingerprint string, op *operations.Operation) e
 	return nil
 }
 
+// UpdateImage updates image config.
+func (b *lxdBackend) UpdateImage(fingerprint, newDesc string, newConfig map[string]string, op *operations.Operation) error {
+	logger := logging.AddContext(b.logger, log.Ctx{"fingerprint": fingerprint, "newDesc": newDesc, "newConfig": newConfig})
+	logger.Debug("UpdateImage started")
+	defer logger.Debug("UpdateImage finished")
+
+	return ErrNotImplemented
+}
+
 // 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})

From 6c8666c023b09ecfbf1d268d2a278f5af479e854 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 17:14:40 +0000
Subject: [PATCH 05/12] lxd/storage/backend/lxd: Adds detectChangedConfig and
 updates usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/backend_lxd.go | 54 ++++++++++++++++++++++----------------
 1 file changed, 31 insertions(+), 23 deletions(-)

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 76a123bc60..4f6a5d62b2 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -2161,6 +2161,36 @@ func (b *lxdBackend) RenameCustomVolume(volName string, newVolName string, op *o
 	return nil
 }
 
+// detectChangedConfig returns the config that has changed between current and new config maps.
+// Also returns a boolean indicating whether all of the changed keys start with "user.".
+// Deleted keys will be returned as having an empty string value.
+func (b *lxdBackend) detectChangedConfig(curConfig, newConfig map[string]string) (map[string]string, bool) {
+	// Diff the configurations.
+	changedConfig := make(map[string]string)
+	userOnly := true
+	for key := range curConfig {
+		if curConfig[key] != newConfig[key] {
+			if !strings.HasPrefix(key, "user.") {
+				userOnly = false
+			}
+
+			changedConfig[key] = newConfig[key] // Will be empty string on deleted keys.
+		}
+	}
+
+	for key := range newConfig {
+		if curConfig[key] != newConfig[key] {
+			if !strings.HasPrefix(key, "user.") {
+				userOnly = false
+			}
+
+			changedConfig[key] = newConfig[key]
+		}
+	}
+
+	return changedConfig, userOnly
+}
+
 // 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})
@@ -2188,30 +2218,8 @@ func (b *lxdBackend) UpdateCustomVolume(volName, newDesc string, newConfig map[s
 		return err
 	}
 
-	// Diff the configurations.
-	changedConfig := make(map[string]string)
-	userOnly := true
-	for key := range curVol.Config {
-		if curVol.Config[key] != newConfig[key] {
-			if !strings.HasPrefix(key, "user.") {
-				userOnly = false
-			}
-
-			changedConfig[key] = newConfig[key] // Will be empty string on deleted keys.
-		}
-	}
-
-	for key := range newConfig {
-		if curVol.Config[key] != newConfig[key] {
-			if !strings.HasPrefix(key, "user.") {
-				userOnly = false
-			}
-
-			changedConfig[key] = newConfig[key]
-		}
-	}
-
 	// Apply config changes if there are any.
+	changedConfig, userOnly := b.detectChangedConfig(curVol.Config, newConfig)
 	if len(changedConfig) != 0 {
 		curVol := b.newVolume(drivers.VolumeTypeCustom, drivers.ContentTypeFS, volName, curVol.Config)
 		if !userOnly {

From b4371e775ebacdeafb780f35698d4f0b7c6764ad Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 17:15:02 +0000
Subject: [PATCH 06/12] lxd/storage/backend/lxd: Switches to
 StoragePoolVolumeUpdateByProject

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

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index 4f6a5d62b2..68468540fe 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -2255,7 +2255,7 @@ func (b *lxdBackend) UpdateCustomVolume(volName, newDesc string, newConfig map[s
 
 	// Update the database if something changed.
 	if len(changedConfig) != 0 || newDesc != curVol.Description {
-		err = b.state.Cluster.StoragePoolVolumeUpdate(volName, db.StoragePoolVolumeTypeCustom, b.ID(), newDesc, newConfig)
+		err = b.state.Cluster.StoragePoolVolumeUpdateByProject("default", volName, db.StoragePoolVolumeTypeCustom, b.ID(), newDesc, newConfig)
 		if err != nil {
 			return err
 		}

From 2dc42e5b6d1db86d1a0dc6a9d552dca34662511f Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 17:15:29 +0000
Subject: [PATCH 07/12] lxd/db/storage/pools: Replaces StoragePoolVolumeUpdate
 with StoragePoolVolumeUpdateByProject

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/db/storage_pools.go | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go
index 02279a36a7..84d44d5075 100644
--- a/lxd/db/storage_pools.go
+++ b/lxd/db/storage_pools.go
@@ -871,16 +871,15 @@ func (c *Cluster) StoragePoolNodeVolumeGetTypeByProject(project, volumeName stri
 	return c.StoragePoolVolumeGetType(project, volumeName, volumeType, poolID, c.nodeID)
 }
 
-// StoragePoolVolumeUpdate updates the storage volume attached to a given storage
-// pool.
-func (c *Cluster) StoragePoolVolumeUpdate(volumeName string, volumeType int, poolID int64, volumeDescription string, volumeConfig map[string]string) error {
-	volumeID, _, err := c.StoragePoolNodeVolumeGetType(volumeName, volumeType, poolID)
+// StoragePoolVolumeUpdateByProject updates the storage volume attached to a given storage pool.
+func (c *Cluster) StoragePoolVolumeUpdateByProject(project, volumeName string, volumeType int, poolID int64, volumeDescription string, volumeConfig map[string]string) error {
+	volumeID, _, err := c.StoragePoolNodeVolumeGetTypeByProject(project, volumeName, volumeType, poolID)
 	if err != nil {
 		return err
 	}
 
 	err = c.Transaction(func(tx *ClusterTx) error {
-		err = storagePoolVolumeReplicateIfCeph(tx.tx, volumeID, "default", volumeName, volumeType, poolID, func(volumeID int64) error {
+		err = storagePoolVolumeReplicateIfCeph(tx.tx, volumeID, project, volumeName, volumeType, poolID, func(volumeID int64) error {
 			err = StorageVolumeConfigClear(tx.tx, volumeID)
 			if err != nil {
 				return err

From 81f395ab05a50f9f11e3e12858f60a83c66cb2e9 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 17:16:59 +0000
Subject: [PATCH 08/12] lxd/storage/volumes: Updates storagePoolVolumeTypePut
 to be project aware

Also handles update requests via the new storage layer.

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage_volumes.go | 48 ++++++++++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 16 deletions(-)

diff --git a/lxd/storage_volumes.go b/lxd/storage_volumes.go
index ef17b367d9..340f91fcc1 100644
--- a/lxd/storage_volumes.go
+++ b/lxd/storage_volumes.go
@@ -12,6 +12,7 @@ import (
 	"github.com/gorilla/mux"
 	"github.com/gorilla/websocket"
 	"github.com/lxc/lxd/lxd/db"
+	"github.com/lxc/lxd/lxd/instance"
 	"github.com/lxc/lxd/lxd/operations"
 	"github.com/lxc/lxd/lxd/response"
 	"github.com/lxc/lxd/lxd/state"
@@ -908,6 +909,8 @@ func storagePoolVolumeTypeImageGet(d *Daemon, r *http.Request) response.Response
 // This function does allow limited functionality for non-custom volume types, specifically you
 // can modify the volume's description only.
 func storagePoolVolumeTypePut(d *Daemon, r *http.Request, volumeTypeName string) response.Response {
+	project := projectParam(r)
+
 	// Get the name of the storage volume.
 	volumeName, err := storageGetVolumeNameFromURL(r)
 	if err != nil {
@@ -945,7 +948,7 @@ func storagePoolVolumeTypePut(d *Daemon, r *http.Request, volumeTypeName string)
 	}
 
 	// Get the existing storage volume.
-	_, vol, err := d.cluster.StoragePoolNodeVolumeGetType(volumeName, volumeType, poolID)
+	_, vol, err := d.cluster.StoragePoolNodeVolumeGetTypeByProject(project, volumeName, volumeType, poolID)
 	if err != nil {
 		return response.SmartError(err)
 	}
@@ -981,31 +984,44 @@ func storagePoolVolumeTypePut(d *Daemon, r *http.Request, volumeTypeName string)
 				}
 			}
 
-			// Handle update requests.
+			// Handle custom volume update requests.
 			err = pool.UpdateCustomVolume(vol.Name, req.Description, req.Config, nil)
 			if err != nil {
 				return response.SmartError(err)
 			}
-		} else {
-			// You are only allowed to modify the description for non-custom volumes.
-			// This is a special case because the rootfs devices do not provide a way
-			// to update a non-custom volume's description.
-			if len(req.Config) > 0 {
-				return response.BadRequest(fmt.Errorf("Only description can be modified for volume type %s", volumeTypeName))
+		} else if volumeType == db.StoragePoolVolumeTypeContainer || volumeType == db.StoragePoolVolumeTypeVM {
+			inst, err := instance.LoadByProjectAndName(d.State(), project, vol.Name)
+			if err != nil {
+				return response.NotFound(err)
 			}
 
 			// There is a bug in the lxc client (lxc/storage_volume.go#L829-L865) which
-			// 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.
-
-			// Update the database if description changed.
-			if req.Description != vol.Description {
-				err = d.cluster.StoragePoolVolumeUpdate(vol.Name, volumeType, poolID, req.Description, vol.Config)
+			// means that modifying an instance snapshot's description gets routed here
+			// rather than the dedicated snapshot editing route. So need to handle
+			// snapshot volumes here too.
+			if inst.IsSnapshot() {
+				// Update the database if description changed. Use current config.
+				if req.Description != vol.Description {
+					err = d.cluster.StoragePoolVolumeUpdateByProject(inst.Project(), inst.Name(), volumeType, poolID, req.Description, vol.Config)
+					if err != nil {
+						response.SmartError(err)
+					}
+				}
+			} else {
+				// Handle instance volume update requests.
+				err = pool.UpdateInstance(inst, req.Description, req.Config, nil)
 				if err != nil {
-					response.SmartError(err)
+					return response.SmartError(err)
 				}
 			}
+		} else if volumeType == db.StoragePoolVolumeTypeImage {
+			// Handle image update requests.
+			err = pool.UpdateImage(vol.Name, req.Description, req.Config, nil)
+			if err != nil {
+				return response.SmartError(err)
+			}
+		} else {
+			return response.SmartError(fmt.Errorf("Invalid volume type"))
 		}
 	} else {
 

From 64aec93e582c1a1f6c4ec6a8802cdbc02e38c0c5 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 17:17:40 +0000
Subject: [PATCH 09/12] lxd/storage/pool/interface: Adds Update functions for
 Instances and Images

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/storage/pool_interface.go | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lxd/storage/pool_interface.go b/lxd/storage/pool_interface.go
index 279d0db79e..274c613a20 100644
--- a/lxd/storage/pool_interface.go
+++ b/lxd/storage/pool_interface.go
@@ -33,6 +33,7 @@ type Pool interface {
 	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
+	UpdateInstance(inst instance.Instance, newDesc string, newConfig map[string]string, 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
@@ -56,6 +57,7 @@ type Pool interface {
 	// Images.
 	EnsureImage(fingerprint string, op *operations.Operation) error
 	DeleteImage(fingerprint string, op *operations.Operation) error
+	UpdateImage(fingerprint, newDesc string, newConfig map[string]string, op *operations.Operation) error
 
 	// Custom volumes.
 	CreateCustomVolume(volName, desc string, config map[string]string, op *operations.Operation) error

From c17566424710d79a0271570bb7301dcc044d6449 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 17:18:09 +0000
Subject: [PATCH 10/12] lxd/storage/drivers/driver/common: Only allow size
 property on custom volumes

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

diff --git a/lxd/storage/drivers/driver_common.go b/lxd/storage/drivers/driver_common.go
index a0cfb0173d..1b022472d2 100644
--- a/lxd/storage/drivers/driver_common.go
+++ b/lxd/storage/drivers/driver_common.go
@@ -76,6 +76,11 @@ func (d *common) validateVolume(vol Volume, driverRules map[string]func(value st
 		}
 	}
 
+	// If volume type is not custom, don't allow "size" property.
+	if vol.volType != VolumeTypeCustom && vol.config["size"] != "" {
+		return fmt.Errorf("Volume 'size' property is only valid for custom volume types")
+	}
+
 	return nil
 }
 

From 3954904039b6ad6d70e8cf42709ff6a84cc58a2e Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 17:19:13 +0000
Subject: [PATCH 11/12] lxd/storage/backend/mock: Adds Update functions for
 Instances and Images

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

diff --git a/lxd/storage/backend_mock.go b/lxd/storage/backend_mock.go
index 9cc026d611..62200e870f 100644
--- a/lxd/storage/backend_mock.go
+++ b/lxd/storage/backend_mock.go
@@ -88,6 +88,10 @@ func (b *mockBackend) DeleteInstance(inst instance.Instance, op *operations.Oper
 	return nil
 }
 
+func (b *mockBackend) UpdateInstance(inst instance.Instance, newDesc string, newConfig map[string]string, op *operations.Operation) error {
+	return nil
+}
+
 func (b *mockBackend) MigrateInstance(inst instance.Instance, conn io.ReadWriteCloser, args migration.VolumeSourceArgs, op *operations.Operation) error {
 	return nil
 }
@@ -152,6 +156,10 @@ func (b *mockBackend) DeleteImage(fingerprint string, op *operations.Operation)
 	return nil
 }
 
+func (b *mockBackend) UpdateImage(fingerprint, newDesc string, newConfig map[string]string, op *operations.Operation) error {
+	return nil
+}
+
 func (b *mockBackend) CreateCustomVolume(volName, desc string, config map[string]string, op *operations.Operation) error {
 	return nil
 }

From 02072ba07252251671c7d549b77df0cbabbf0312 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Fri, 13 Dec 2019 17:19:38 +0000
Subject: [PATCH 12/12] lxd: Updates StoragePoolVolumeUpdateByProject usage

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/db/storage_pools_test.go    |  2 +-
 lxd/patches.go                  | 30 +++++++++++++++---------------
 lxd/storage.go                  |  2 +-
 lxd/storage_ceph.go             |  3 ++-
 lxd/storage_lvm.go              |  3 ++-
 lxd/storage_volumes.go          |  2 +-
 lxd/storage_volumes_snapshot.go |  2 +-
 lxd/storage_volumes_utils.go    |  2 +-
 8 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/lxd/db/storage_pools_test.go b/lxd/db/storage_pools_test.go
index 5b78255ad9..7871cfa8be 100644
--- a/lxd/db/storage_pools_test.go
+++ b/lxd/db/storage_pools_test.go
@@ -184,7 +184,7 @@ func TestStoragePoolVolume_Ceph(t *testing.T) {
 
 	// Update the volume
 	config["k"] = "v2"
-	err = cluster.StoragePoolVolumeUpdate("v1", 1, poolID, "volume 1", config)
+	err = cluster.StoragePoolVolumeUpdateByProject("default", "v1", 1, poolID, "volume 1", config)
 	require.NoError(t, err)
 	for _, nodeID := range []int64{1, 2} {
 		_, volume, err := cluster.StoragePoolVolumeGetType("default", "v1", 1, poolID, nodeID)
diff --git a/lxd/patches.go b/lxd/patches.go
index 99923e43cf..3049b08896 100644
--- a/lxd/patches.go
+++ b/lxd/patches.go
@@ -480,7 +480,7 @@ func upgradeFromStorageTypeBtrfs(name string, d *Daemon, defaultPoolName string,
 		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(ct, storagePoolVolumeTypeContainer, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the container")
-			err := d.cluster.StoragePoolVolumeUpdate(ct, storagePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", ct, storagePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
 			if err != nil {
 				return err
 			}
@@ -568,7 +568,7 @@ func upgradeFromStorageTypeBtrfs(name string, d *Daemon, defaultPoolName string,
 			_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(cs, storagePoolVolumeTypeContainer, poolID)
 			if err == nil {
 				logger.Warnf("Storage volumes database already contains an entry for the snapshot")
-				err := d.cluster.StoragePoolVolumeUpdate(cs, storagePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
+				err := d.cluster.StoragePoolVolumeUpdateByProject("default", cs, storagePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
 				if err != nil {
 					return err
 				}
@@ -649,7 +649,7 @@ func upgradeFromStorageTypeBtrfs(name string, d *Daemon, defaultPoolName string,
 		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(img, storagePoolVolumeTypeImage, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the image")
-			err := d.cluster.StoragePoolVolumeUpdate(img, storagePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", img, storagePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
 			if err != nil {
 				return err
 			}
@@ -767,7 +767,7 @@ func upgradeFromStorageTypeDir(name string, d *Daemon, defaultPoolName string, d
 		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(ct, storagePoolVolumeTypeContainer, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the container")
-			err := d.cluster.StoragePoolVolumeUpdate(ct, storagePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", ct, storagePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
 			if err != nil {
 				return err
 			}
@@ -884,7 +884,7 @@ func upgradeFromStorageTypeDir(name string, d *Daemon, defaultPoolName string, d
 		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(cs, storagePoolVolumeTypeContainer, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the snapshot")
-			err := d.cluster.StoragePoolVolumeUpdate(cs, storagePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", cs, storagePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
 			if err != nil {
 				return err
 			}
@@ -914,7 +914,7 @@ func upgradeFromStorageTypeDir(name string, d *Daemon, defaultPoolName string, d
 		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(img, storagePoolVolumeTypeImage, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the image")
-			err := d.cluster.StoragePoolVolumeUpdate(img, storagePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", img, storagePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
 			if err != nil {
 				return err
 			}
@@ -1076,7 +1076,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
 		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(ct, storagePoolVolumeTypeContainer, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the container")
-			err := d.cluster.StoragePoolVolumeUpdate(ct, storagePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", ct, storagePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
 			if err != nil {
 				return err
 			}
@@ -1231,7 +1231,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
 			_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(cs, storagePoolVolumeTypeContainer, poolID)
 			if err == nil {
 				logger.Warnf("Storage volumes database already contains an entry for the snapshot")
-				err := d.cluster.StoragePoolVolumeUpdate(cs, storagePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
+				err := d.cluster.StoragePoolVolumeUpdateByProject("default", cs, storagePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
 				if err != nil {
 					return err
 				}
@@ -1402,7 +1402,7 @@ func upgradeFromStorageTypeLvm(name string, d *Daemon, defaultPoolName string, d
 		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(img, storagePoolVolumeTypeImage, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the image")
-			err := d.cluster.StoragePoolVolumeUpdate(img, storagePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", img, storagePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
 			if err != nil {
 				return err
 			}
@@ -1594,7 +1594,7 @@ func upgradeFromStorageTypeZfs(name string, d *Daemon, defaultPoolName string, d
 		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(ct, storagePoolVolumeTypeContainer, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the container")
-			err := d.cluster.StoragePoolVolumeUpdate(ct, storagePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", ct, storagePoolVolumeTypeContainer, poolID, "", containerPoolVolumeConfig)
 			if err != nil {
 				return err
 			}
@@ -1680,7 +1680,7 @@ func upgradeFromStorageTypeZfs(name string, d *Daemon, defaultPoolName string, d
 			_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(cs, storagePoolVolumeTypeContainer, poolID)
 			if err == nil {
 				logger.Warnf("Storage volumes database already contains an entry for the snapshot")
-				err := d.cluster.StoragePoolVolumeUpdate(cs, storagePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
+				err := d.cluster.StoragePoolVolumeUpdateByProject("default", cs, storagePoolVolumeTypeContainer, poolID, "", snapshotPoolVolumeConfig)
 				if err != nil {
 					return err
 				}
@@ -1736,7 +1736,7 @@ func upgradeFromStorageTypeZfs(name string, d *Daemon, defaultPoolName string, d
 		_, err = d.cluster.StoragePoolNodeVolumeGetTypeID(img, storagePoolVolumeTypeImage, poolID)
 		if err == nil {
 			logger.Warnf("Storage volumes database already contains an entry for the image")
-			err := d.cluster.StoragePoolVolumeUpdate(img, storagePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
+			err := d.cluster.StoragePoolVolumeUpdateByProject("default", img, storagePoolVolumeTypeImage, poolID, "", imagePoolVolumeConfig)
 			if err != nil {
 				return err
 			}
@@ -2290,7 +2290,7 @@ func patchStorageApiUpdateStorageConfigs(name string, d *Daemon) error {
 			// exist in the db, so it's safe to ignore the error.
 			volumeType, _ := driver.VolumeTypeNameToType(volume.Type)
 			// Update the volume config.
-			err = d.cluster.StoragePoolVolumeUpdate(volume.Name, volumeType, poolID, volume.Description, volume.Config)
+			err = d.cluster.StoragePoolVolumeUpdateByProject("default", volume.Name, volumeType, poolID, volume.Description, volume.Config)
 			if err != nil {
 				return err
 			}
@@ -2438,7 +2438,7 @@ func patchStorageApiDetectLVSize(name string, d *Daemon) error {
 			// exist in the db, so it's safe to ignore the error.
 			volumeType, _ := driver.VolumeTypeNameToType(volume.Type)
 			// Update the volume config.
-			err = d.cluster.StoragePoolVolumeUpdate(volume.Name, volumeType, poolID, volume.Description, volume.Config)
+			err = d.cluster.StoragePoolVolumeUpdateByProject("default", volume.Name, volumeType, poolID, volume.Description, volume.Config)
 			if err != nil {
 				return err
 			}
@@ -2568,7 +2568,7 @@ func patchStorageZFSVolumeSize(name string, d *Daemon) error {
 			// exist in the db, so it's safe to ignore the error.
 			volumeType, _ := driver.VolumeTypeNameToType(volume.Type)
 			// Update the volume config.
-			err = d.cluster.StoragePoolVolumeUpdate(volume.Name,
+			err = d.cluster.StoragePoolVolumeUpdateByProject("default", volume.Name,
 				volumeType, poolID, volume.Description,
 				volume.Config)
 			if err != nil {
diff --git a/lxd/storage.go b/lxd/storage.go
index ff3f67ca55..af02e505c5 100644
--- a/lxd/storage.go
+++ b/lxd/storage.go
@@ -566,7 +566,7 @@ func storagePoolVolumeAttachPrepare(s *state.State, poolName string, volumeName
 	// Update last idmap
 	poolVolumePut.Config["volatile.idmap.last"] = jsonIdmap
 
-	err = s.Cluster.StoragePoolVolumeUpdate(volumeName, volumeType, poolID, poolVolumePut.Description, poolVolumePut.Config)
+	err = s.Cluster.StoragePoolVolumeUpdateByProject("default", volumeName, volumeType, poolID, poolVolumePut.Description, poolVolumePut.Config)
 	if err != nil {
 		return err
 	}
diff --git a/lxd/storage_ceph.go b/lxd/storage_ceph.go
index 750112b03c..1b5729e8e7 100644
--- a/lxd/storage_ceph.go
+++ b/lxd/storage_ceph.go
@@ -2443,7 +2443,8 @@ func (s *storageCeph) StorageEntitySetQuota(volumeType int, size int64, data int
 
 	// Update the database
 	s.volume.Config["size"] = units.GetByteSizeString(size, 0)
-	err = s.s.Cluster.StoragePoolVolumeUpdate(
+	err = s.s.Cluster.StoragePoolVolumeUpdateByProject(
+		"default",
 		s.volume.Name,
 		volumeType,
 		s.poolID,
diff --git a/lxd/storage_lvm.go b/lxd/storage_lvm.go
index 2a8d924972..e4cab25c5e 100644
--- a/lxd/storage_lvm.go
+++ b/lxd/storage_lvm.go
@@ -2122,7 +2122,8 @@ func (s *storageLvm) StorageEntitySetQuota(volumeType int, size int64, data inte
 
 	// Update the database
 	s.volume.Config["size"] = units.GetByteSizeString(size, 0)
-	err = s.s.Cluster.StoragePoolVolumeUpdate(
+	err = s.s.Cluster.StoragePoolVolumeUpdateByProject(
+		"default",
 		s.volume.Name,
 		volumeType,
 		s.poolID,
diff --git a/lxd/storage_volumes.go b/lxd/storage_volumes.go
index 340f91fcc1..0efd6460d3 100644
--- a/lxd/storage_volumes.go
+++ b/lxd/storage_volumes.go
@@ -873,7 +873,7 @@ func storagePoolVolumeTypeGet(d *Daemon, r *http.Request, volumeTypeName string)
 	}
 
 	// Get the storage volume.
-	_, volume, err := d.cluster.StoragePoolNodeVolumeGetType(volumeName, volumeType, poolID)
+	_, volume, err := d.cluster.StoragePoolNodeVolumeGetTypeByProject(project, volumeName, volumeType, poolID)
 	if err != nil {
 		return response.SmartError(err)
 	}
diff --git a/lxd/storage_volumes_snapshot.go b/lxd/storage_volumes_snapshot.go
index d81698513e..cb939f6527 100644
--- a/lxd/storage_volumes_snapshot.go
+++ b/lxd/storage_volumes_snapshot.go
@@ -461,7 +461,7 @@ func storagePoolVolumeSnapshotTypePut(d *Daemon, r *http.Request) response.Respo
 	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)
+			err = d.cluster.StoragePoolVolumeUpdateByProject("default", vol.Name, volumeType, poolID, req.Description, vol.Config)
 			if err != nil {
 				return err
 			}
diff --git a/lxd/storage_volumes_utils.go b/lxd/storage_volumes_utils.go
index 40d8ca789a..51fa6ef38e 100644
--- a/lxd/storage_volumes_utils.go
+++ b/lxd/storage_volumes_utils.go
@@ -202,7 +202,7 @@ func storagePoolVolumeUpdate(state *state.State, poolName string, volumeName str
 
 	// Update the database if something changed
 	if len(changedConfig) != 0 || newDescription != oldDescription {
-		err = state.Cluster.StoragePoolVolumeUpdate(volumeName, volumeType, poolID, newDescription, newConfig)
+		err = state.Cluster.StoragePoolVolumeUpdateByProject("default", volumeName, volumeType, poolID, newDescription, newConfig)
 		if err != nil {
 			return err
 		}


More information about the lxc-devel mailing list