[lxc-devel] [lxd/master] Storage EnsureImage filesystem regeneration

tomponline on Github lxc-bot at linuxcontainers.org
Thu Jan 9 19:39:19 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 451 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200109/6ddc4730/attachment.bin>
-------------- next part --------------
From 01d9c0a3bc0aeb2f34b519476738d247efc279e7 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 9 Jan 2020 19:35:32 +0000
Subject: [PATCH 1/3] lxd/storage/drivers/volume: Adds DefaultFilesystem
 constant of ext4

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

diff --git a/lxd/storage/drivers/volume.go b/lxd/storage/drivers/volume.go
index fcba388445..ce968b7645 100644
--- a/lxd/storage/drivers/volume.go
+++ b/lxd/storage/drivers/volume.go
@@ -11,6 +11,9 @@ import (
 
 var defaultBlockSize = "10GB"
 
+// DefaultFilesystem filesytem to use for block devices by default.
+var DefaultFilesystem = "ext4"
+
 var volIDQuotaSkip = int64(-1)
 
 // VolumeType represents a storage volume type.

From c6dff25631f33f0898f7258cdb6e3a1948c21bda Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 9 Jan 2020 19:35:08 +0000
Subject: [PATCH 2/3] lxd/storage/utils: Uses DefaultFilesystem in
 VolumeFillDefault

Signed-off-by: Thomas Parrott <thomas.parrott at 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 0790164ca9..a2f2969542 100644
--- a/lxd/storage/utils.go
+++ b/lxd/storage/utils.go
@@ -447,7 +447,7 @@ func VolumeFillDefault(name string, config map[string]string, parentPool *api.St
 		}
 		if config["block.filesystem"] == "" {
 			// Unchangeable volume property: Set unconditionally.
-			config["block.filesystem"] = "ext4"
+			config["block.filesystem"] = drivers.DefaultFilesystem
 		}
 
 		if config["block.mount_options"] == "" {

From 314aa97421e27d24a57d43ae85a801a874302dbf Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 9 Jan 2020 19:34:36 +0000
Subject: [PATCH 3/3] lxd/storage/backend/lxd: Updates EnsureImage to detech
 filesystem changes and regenerate

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

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index d9bc9439ea..41409f25eb 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -1807,6 +1807,15 @@ func (b *lxdBackend) UnmountInstanceSnapshot(inst instance.Instance, op *operati
 	return b.driver.UnmountVolumeSnapshot(vol, op)
 }
 
+// poolBlockFilesystem returns the filesystem used for new block device filesystems.
+func (b *lxdBackend) poolBlockFilesystem() string {
+	if b.db.Config["volume.block.filesystem"] != "" {
+		return b.db.Config["volume.block.filesystem"]
+	}
+
+	return drivers.DefaultFilesystem
+}
+
 // EnsureImage creates an optimized volume of the image if supported by the storage pool driver and
 // the volume doesn't already exist.
 func (b *lxdBackend) EnsureImage(fingerprint string, op *operations.Operation) error {
@@ -1824,31 +1833,48 @@ func (b *lxdBackend) EnsureImage(fingerprint string, op *operations.Operation) e
 	unlock := locking.Lock(b.name, string(drivers.VolumeTypeImage), fmt.Sprintf("EnsureImage_%v", fingerprint))
 	defer unlock()
 
-	// There's no need to pass the content type or config. Both are not needed
-	// when checking the existence of volumes.
-	vol := b.newVolume(drivers.VolumeTypeImage, "", fingerprint, nil)
-
-	// Check if we already have a suitable volume.
-	if b.driver.HasVolume(vol) {
-		return nil
-	}
-
 	// Load image info from database.
 	_, image, err := b.state.Cluster.ImageGetFromAnyProject(fingerprint)
 	if err != nil {
 		return err
 	}
 
+	// Derive content type from image type. Image types are not the same as instance types, so don't use
+	// instance type constants for comparison.
 	contentType := drivers.ContentTypeFS
-
-	// Image types are not the same as instance types, so don't use instance type constants.
 	if image.Type == "virtual-machine" {
 		contentType = drivers.ContentTypeBlock
 	}
 
+	// Try and load any existing volume config on this storage pool so we can compare filesystems if needed.
+	_, imgDBVol, err := b.state.Cluster.StoragePoolNodeVolumeGetTypeByProject("default", fingerprint, db.StoragePoolVolumeTypeImage, b.ID())
+	if err != nil {
+		if err != db.ErrNoSuchObject {
+			return err
+		}
+	}
+
+	// If an existing DB row was found, check if filesystem is the same as the current pool's filesystem.
+	// If not we need to delete the existing cached image volume and re-create using new filesystem.
+	if imgDBVol != nil && contentType == drivers.ContentTypeFS {
+		if imgDBVol.Config["block.filesystem"] != b.poolBlockFilesystem() {
+			logger.Debug("Filesystem of pool has changed since cached image volume created, regenerating image volume")
+			err = b.DeleteImage(fingerprint, op)
+			if err != nil {
+				return err
+			}
+		}
+	}
+
 	// Create the new image volume. No config for an image volume so set to nil.
+	// Pool config values will be read by the underlying driver if needed.
 	imgVol := b.newVolume(drivers.VolumeTypeImage, contentType, fingerprint, nil)
 
+	// Check if we already have a suitable volume on storage device.
+	if b.driver.HasVolume(imgVol) {
+		return nil
+	}
+
 	volFiller := drivers.VolumeFiller{
 		Fingerprint: fingerprint,
 		Fill:        b.imageFiller(fingerprint, op),


More information about the lxc-devel mailing list