[lxc-devel] [lxd/master] Allow deleting storage pools that only contain image volumes

monstermunchkin on Github lxc-bot at linuxcontainers.org
Fri Jul 20 16:07:03 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 314 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180720/291d8360/attachment.bin>
-------------- next part --------------
From e5978642a44c84b636c0c757591d0e40cc8bcf66 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Fri, 20 Jul 2018 15:58:37 +0200
Subject: [PATCH 1/2] Allow deleting storage pools that only contain image
 volumes

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 lxd/storage_pools.go   | 34 +++++++++++++++++++++++++++++++++-
 test/suites/storage.sh | 14 ++++++++++++++
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/lxd/storage_pools.go b/lxd/storage_pools.go
index 192f20afd..4f3799715 100644
--- a/lxd/storage_pools.go
+++ b/lxd/storage_pools.go
@@ -557,6 +557,18 @@ func storagePoolDelete(d *Daemon, r *http.Request) Response {
 		return EmptySyncResponse
 	}
 
+	volumeNames, err := d.cluster.StoragePoolVolumesGetNames(poolID)
+	if err != nil {
+		return InternalError(err)
+	}
+
+	for _, volume := range volumeNames {
+		err = d.cluster.StoragePoolVolumeDelete(volume, storagePoolVolumeTypeImage, poolID)
+		if err != nil {
+			return InternalError(err)
+		}
+	}
+
 	err = s.StoragePoolDelete()
 	if err != nil {
 		return InternalError(err)
@@ -605,7 +617,27 @@ func storagePoolDeleteCheckPreconditions(cluster *db.Cluster, poolName string, p
 	}
 
 	if len(volumeNames) > 0 {
-		return BadRequest(fmt.Errorf("storage pool \"%s\" has volumes attached to it", poolName))
+		volumes, err := cluster.StoragePoolVolumesGet(poolID, supportedVolumeTypes)
+		if err != nil {
+			return InternalError(err)
+		}
+
+		for _, volume := range volumes {
+			if volume.Type != "image" {
+				return BadRequest(fmt.Errorf("storage pool \"%s\" has volumes attached to it", poolName))
+			}
+
+			pools, err := cluster.ImageGetPools(volume.Name)
+			if err != nil {
+				return InternalError(err)
+			}
+
+			// The pool volume/image is used by this pool only. We should fail
+			// here since we don't actually want to have to remove images.
+			if len(pools) == 1 {
+				return BadRequest(fmt.Errorf("storage pool \"%s\" has volumes attached to it", poolName))
+			}
+		}
 	}
 
 	// Check if the storage pool is still referenced in any profiles.
diff --git a/test/suites/storage.sh b/test/suites/storage.sh
index 88ba169b3..1e9e1b6a1 100644
--- a/test/suites/storage.sh
+++ b/test/suites/storage.sh
@@ -794,6 +794,20 @@ test_storage() {
     lxc delete -f quota3
   fi
 
+  # Test removing storage pools only containing image volumes
+  # shellcheck disable=SC2031
+  LXD_DIR="${LXD_DIR}"
+  storage_pool="lxdtest-$(basename "${LXD_DIR}")-pool26"
+  lxc storage create "$storage_pool" "$lxd_backend"
+  lxc init -s "${storage_pool}" testimage c1
+  # The storage pool will not be removed since it has c1 attached to it
+  ! lxc storage delete "${storage_pool}"
+  lxc delete c1
+  # The storage pool will be deleted since the testimage is also attached to
+  # the default pool
+  lxc storage delete "${storage_pool}"
+  lxc image show testimage
+
   # shellcheck disable=SC2031
   LXD_DIR="${LXD_DIR}"
   kill_lxd "${LXD_STORAGE_DIR}"

From c9fe01dde87d5bc8f4480e69aaf39a964c3a69e7 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Fri, 20 Jul 2018 17:24:03 +0200
Subject: [PATCH 2/2] lxd/storage: Remove image on pool deletion

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 lxd/storage_pools.go | 53 ++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 41 insertions(+), 12 deletions(-)

diff --git a/lxd/storage_pools.go b/lxd/storage_pools.go
index 4f3799715..605daf9e3 100644
--- a/lxd/storage_pools.go
+++ b/lxd/storage_pools.go
@@ -15,6 +15,7 @@ import (
 	"github.com/lxc/lxd/lxd/util"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
+	"github.com/lxc/lxd/shared/logger"
 	"github.com/lxc/lxd/shared/version"
 )
 
@@ -563,10 +564,49 @@ func storagePoolDelete(d *Daemon, r *http.Request) Response {
 	}
 
 	for _, volume := range volumeNames {
-		err = d.cluster.StoragePoolVolumeDelete(volume, storagePoolVolumeTypeImage, poolID)
+		pools, err := d.cluster.ImageGetPools(volume)
 		if err != nil {
 			return InternalError(err)
 		}
+
+		if len(pools) == 1 {
+			imgID, imgInfo, err := d.cluster.ImageGet(volume, false, false)
+			if err != nil {
+				return InternalError(err)
+			}
+
+			err = doDeleteImageFromPool(d.State(), imgInfo.Fingerprint, poolName)
+			if err != nil {
+				return InternalError(err)
+			}
+
+			// Remove main image file.
+			fname := shared.VarPath("images", imgInfo.Fingerprint)
+			if shared.PathExists(fname) {
+				err = os.Remove(fname)
+				if err != nil {
+					logger.Debugf("Error deleting image file %s: %s", fname, err)
+				}
+			}
+
+			// Remove the rootfs file for the image.
+			fname = shared.VarPath("images", imgInfo.Fingerprint) + ".rootfs"
+			if shared.PathExists(fname) {
+				err = os.Remove(fname)
+				if err != nil {
+					logger.Debugf("Error deleting image file %s: %s", fname, err)
+				}
+			}
+
+			// Remove the database entry for the image.
+			d.cluster.ImageDelete(imgID)
+		} else if len(pools) > 1 {
+			// Remove DB entry
+			err = d.cluster.StoragePoolVolumeDelete(volume, storagePoolVolumeTypeImage, poolID)
+			if err != nil {
+				return InternalError(err)
+			}
+		}
 	}
 
 	err = s.StoragePoolDelete()
@@ -626,17 +666,6 @@ func storagePoolDeleteCheckPreconditions(cluster *db.Cluster, poolName string, p
 			if volume.Type != "image" {
 				return BadRequest(fmt.Errorf("storage pool \"%s\" has volumes attached to it", poolName))
 			}
-
-			pools, err := cluster.ImageGetPools(volume.Name)
-			if err != nil {
-				return InternalError(err)
-			}
-
-			// The pool volume/image is used by this pool only. We should fail
-			// here since we don't actually want to have to remove images.
-			if len(pools) == 1 {
-				return BadRequest(fmt.Errorf("storage pool \"%s\" has volumes attached to it", poolName))
-			}
 		}
 	}
 


More information about the lxc-devel mailing list