[lxc-devel] [lxd/master] lxd/storage: Rely on UsedBy for deletion error

stgraber on Github lxc-bot at linuxcontainers.org
Fri Jun 26 20:12:25 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 354 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200626/aebc01d9/attachment.bin>
-------------- next part --------------
From 45acc77df4bdb971d2fd0f19cd6b6d3b29544fd7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 26 Jun 2020 16:04:33 -0400
Subject: [PATCH] lxd/storage: Rely on UsedBy for deletion error
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/storage_pools.go | 72 ++++++++++++++------------------------------
 1 file changed, 23 insertions(+), 49 deletions(-)

diff --git a/lxd/storage_pools.go b/lxd/storage_pools.go
index 98cbbbb4c8..b24443404b 100644
--- a/lxd/storage_pools.go
+++ b/lxd/storage_pools.go
@@ -60,6 +60,7 @@ func storagePoolsGet(d *Daemon, r *http.Request) response.Response {
 			if err != nil {
 				continue
 			}
+
 			// Get all users of the storage pool.
 			poolUsedBy := []string{}
 			err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
@@ -559,9 +560,28 @@ func storagePoolDelete(d *Daemon, r *http.Request) response.Response {
 	// If this is not an internal cluster request, check if the storage
 	// pool has any volumes associated with it, if so error out.
 	if !isClusterNotification(r) {
-		response := storagePoolDeleteCheckPreconditions(d.cluster, poolName, poolID)
-		if response != nil {
-			return response
+		// Get all users of the storage pool.
+		poolUsedBy := []string{}
+		err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
+			poolUsedBy, err = tx.GetStoragePoolUsedBy(poolName)
+			return err
+		})
+		if err != nil {
+			return response.SmartError(err)
+		}
+
+		blocking := []string{}
+		for _, entry := range poolUsedBy {
+			// Image are never a deletion blocker.
+			if strings.HasPrefix(entry, "/1.0/images/") {
+				continue
+			}
+
+			blocking = append(blocking, entry)
+		}
+
+		if len(blocking) > 0 {
+			return response.BadRequest(fmt.Errorf("The pool is currently in use by:\n - %s", strings.Join(blocking, "\n - ")))
 		}
 	}
 
@@ -644,49 +664,3 @@ func storagePoolDelete(d *Daemon, r *http.Request) response.Response {
 
 	return response.EmptySyncResponse
 }
-
-func storagePoolDeleteCheckPreconditions(cluster *db.Cluster, poolName string, poolID int64) response.Response {
-	volumeNames, err := cluster.GetStoragePoolVolumesNames(poolID)
-	if err != nil {
-		return response.InternalError(err)
-	}
-
-	var projects []string
-
-	err = cluster.Transaction(func(tx *db.ClusterTx) error {
-		projects, err = tx.GetProjectNames()
-		return err
-	})
-	if err != nil {
-		return response.InternalError(err)
-	}
-
-	if len(volumeNames) > 0 {
-		for _, project := range projects {
-			volumes, err := cluster.GetStoragePoolVolumes(project, poolID, supportedVolumeTypes)
-			if err != nil {
-				return response.InternalError(err)
-			}
-
-			for _, volume := range volumes {
-				if volume.Type != "image" {
-					return response.BadRequest(fmt.Errorf("storage pool %q has volumes attached to it", poolName))
-				}
-			}
-		}
-	}
-
-	for _, project := range projects {
-		// Check if the storage pool is still referenced in any profiles.
-		profiles, err := profilesUsingPoolGetNames(cluster, project, poolName)
-		if err != nil {
-			return response.SmartError(err)
-		}
-
-		if len(profiles) > 0 {
-			return response.BadRequest(fmt.Errorf("Storage pool %q has profiles using it:\n%s", poolName, strings.Join(profiles, "\n")))
-		}
-	}
-
-	return nil
-}


More information about the lxc-devel mailing list