The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/4817
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) === Closes #4792
From e5978642a44c84b636c0c757591d0e40cc8bcf66 Mon Sep 17 00:00:00 2001 From: Thomas Hipp <thomas.h...@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.h...@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.h...@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.h...@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)) - } } }
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel