[lxc-devel] [lxd/master] Storage: Allow unsafe resize when filling initial image volume

tomponline on Github lxc-bot at linuxcontainers.org
Tue Nov 24 23:26:21 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 598 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20201124/b17b59ac/attachment.bin>
-------------- next part --------------
From 5100d11c0694b767f938eca1673bc1f71bbd6bf9 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 24 Nov 2020 23:10:14 +0000
Subject: [PATCH 1/6] lxd/instance: Use revert package in
 instanceCreateFromImage

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

diff --git a/lxd/instance.go b/lxd/instance.go
index 45aed86b17..515f7bc414 100644
--- a/lxd/instance.go
+++ b/lxd/instance.go
@@ -149,14 +149,9 @@ func instanceCreateFromImage(d *Daemon, args db.InstanceArgs, hash string, op *o
 		return nil, errors.Wrap(err, "Failed creating instance record")
 	}
 
-	revert := true
-	defer func() {
-		if !revert {
-			return
-		}
-
-		inst.Delete()
-	}()
+	revert := revert.New()
+	defer revert.Fail()
+	revert.Add(func() { inst.Delete() })
 
 	err = s.Cluster.UpdateImageLastUseDate(hash, time.Now().UTC())
 	if err != nil {
@@ -178,7 +173,7 @@ func instanceCreateFromImage(d *Daemon, args db.InstanceArgs, hash string, op *o
 		return nil, err
 	}
 
-	revert = false
+	revert.Success()
 	return inst, nil
 }
 

From dc9de71602879cc4b137f36bac8952a11417102a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 24 Nov 2020 23:10:40 +0000
Subject: [PATCH 2/6] lxd/storage/backend/lxd: Remove revert from
 CreateInstanceFromImage

Expect caller to call DeleteInstance on failure (due to this function not creating the storage DB record and upstream callers are also trying to remove it on failure).

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

diff --git a/lxd/storage/backend_lxd.go b/lxd/storage/backend_lxd.go
index a2c86b94e9..ffb6d75699 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -1003,6 +1003,7 @@ func (b *lxdBackend) imageFiller(fingerprint string, op *operations.Operation) f
 }
 
 // CreateInstanceFromImage creates a new volume for an instance populated with the image requested.
+// On failure caller is expected to call DeleteInstance() to clean up.
 func (b *lxdBackend) CreateInstanceFromImage(inst instance.Instance, fingerprint string, op *operations.Operation) error {
 	logger := logging.AddContext(b.logger, log.Ctx{"project": inst.Project(), "instance": inst.Name()})
 	logger.Debug("CreateInstanceFromImage started")
@@ -1026,9 +1027,7 @@ func (b *lxdBackend) CreateInstanceFromImage(inst instance.Instance, fingerprint
 
 	vol := b.newVolume(volType, contentType, volStorageName, rootDiskConf)
 
-	revert := revert.New()
-	defer revert.Fail()
-	revert.Add(func() { b.DeleteInstance(inst, op) })
+	// Leave reverting on failure to caller, they are expected to call DeleteInstance().
 
 	// If the driver doesn't support optimized image volumes then create a new empty volume and
 	// populate it with the contents of the image archive.
@@ -1106,7 +1105,6 @@ func (b *lxdBackend) CreateInstanceFromImage(inst instance.Instance, fingerprint
 		return err
 	}
 
-	revert.Success()
 	return nil
 }
 

From 8edbfff9d88caa82615ef5545135d67805658ae0 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 24 Nov 2020 23:11:33 +0000
Subject: [PATCH 3/6] lxd/storage/drivers/driver/common: Enable unsafe resize
 mode in runFiller when unpacking into image volumes

This allows image volumes to grow to accomodate larger images even on storage drivers that usually don't allow image volumes to be resized due to their read-only snapshots, as these have not been taken yet.

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

diff --git a/lxd/storage/drivers/driver_common.go b/lxd/storage/drivers/driver_common.go
index 1aaa5561fe..f34d18a972 100644
--- a/lxd/storage/drivers/driver_common.go
+++ b/lxd/storage/drivers/driver_common.go
@@ -242,6 +242,15 @@ func (d *common) runFiller(vol Volume, devPath string, filler *VolumeFiller) err
 		return nil
 	}
 
+	// Allow filler to resize initial image volume as needed. Some storage drivers don't normally allow
+	// image volumes to be resized due to them having read-only snapshots that cannot be resized. However
+	// when creating the initial image volume and filling it before the snapshot is taken resizing can be
+	// allowed and is required in order to support unpacking images larger than the default volume size.
+	// The filler function is still expected to obey any volume size restrictions configured on the pool.
+	if vol.Type() == VolumeTypeImage {
+		vol.allowUnsafeResize = true
+	}
+
 	vol.driver.Logger().Debug("Running filler function", log.Ctx{"dev": devPath, "path": vol.MountPath()})
 	volSize, err := filler.Fill(vol, devPath)
 	if err != nil {

From 922aca2f0426ce34f146c05a869e7f6afa8bbcb0 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 24 Nov 2020 23:13:04 +0000
Subject: [PATCH 4/6] lxd/storage/drivers/driver/ceph/volume: Allow image
 resize when in unsafe mode in SetVolumeQuota

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

diff --git a/lxd/storage/drivers/driver_ceph_volumes.go b/lxd/storage/drivers/driver_ceph_volumes.go
index 8d1b302236..b167a71f29 100644
--- a/lxd/storage/drivers/driver_ceph_volumes.go
+++ b/lxd/storage/drivers/driver_ceph_volumes.go
@@ -872,7 +872,8 @@ func (d *ceph) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
 
 	// Block image volumes cannot be resized because they have a readonly snapshot that doesn't get
 	// updated when the volume's size is changed, and this is what instances are created from.
-	if vol.volType == VolumeTypeImage {
+	// During initial volume fill allowUnsafeResize is enabled because snapshot hasn't been taken yet.
+	if !vol.allowUnsafeResize && vol.volType == VolumeTypeImage {
 		return ErrNotSupported
 	}
 

From 82586e064b400a6fab43e72aed446839cb6f003a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 24 Nov 2020 23:13:31 +0000
Subject: [PATCH 5/6] lxd/storage/drivers/driver/zfs/volume: Allow image resize
 when in unsafe mode in SetVolumeQuota

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

diff --git a/lxd/storage/drivers/driver_zfs_volumes.go b/lxd/storage/drivers/driver_zfs_volumes.go
index 958c6c2d27..42e8056d1b 100644
--- a/lxd/storage/drivers/driver_zfs_volumes.go
+++ b/lxd/storage/drivers/driver_zfs_volumes.go
@@ -940,7 +940,8 @@ func (d *zfs) SetVolumeQuota(vol Volume, size string, op *operations.Operation)
 
 		// Block image volumes cannot be resized because they have a readonly snapshot that doesn't get
 		// updated when the volume's size is changed, and this is what instances are created from.
-		if vol.volType == VolumeTypeImage {
+		// During initial volume fill allowUnsafeResize is enabled because snapshot hasn't been taken yet.
+		if !vol.allowUnsafeResize && vol.volType == VolumeTypeImage {
 			return ErrNotSupported
 		}
 

From 71ce592260ae05081f3b687ee5ffc94325f22e3c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Tue, 24 Nov 2020 23:23:55 +0000
Subject: [PATCH 6/6] lxd/storage/backend/lxd: Log new volume size in
 CreateInstanceFromImage

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 ffb6d75699..79a72c541e 100644
--- a/lxd/storage/backend_lxd.go
+++ b/lxd/storage/backend_lxd.go
@@ -1069,6 +1069,7 @@ func (b *lxdBackend) CreateInstanceFromImage(inst instance.Instance, fingerprint
 
 		// Set the derived size directly as the "size" property on the new volume so that it is applied.
 		vol.SetConfigSize(newVolSize)
+		logger.Debug("Set new volume size", log.Ctx{"size": newVolSize})
 
 		// Proceed to create a new volume by copying the optimized image volume.
 		err = b.driver.CreateVolumeFromCopy(vol, imgVol, false, op)


More information about the lxc-devel mailing list