The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/7283

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) ===
Updates dir, btrfs, lvm, zfs and ceph drivers to behave in a consistent way in terms of setting volume size (be it block volume size or quota).

Ensures that:

- `SetVolumeQuota()` function does nothing when supplied with a "0" or "" size argument for block volumes and removes quota if driver uses quotas.
- `volumeSize()` function returns the value of `vol.ExpandedConfig("size")` (which takes the size from volume config or pool config) and if not specified in either will return the `defaultBlockSize` if relevant for the driver (i.e for block backed drivers always return it, and for non-block-backed drivers only return it if creating a block volume).

Tested:

- [ ] btrfs
- [ ] ceph
- [ ] dir
- [ ] lvm
- [ ] zfs

From 970117bf3834e3a1eb1e5a5ad5636a85496d5c2b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:09:14 +0100
Subject: [PATCH 01/17] lxd/storage/drivers/utils: Updates
 roundVolumeBlockFileSizeBytes to take byte size

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/utils.go | 30 ++++++++++++------------------
 1 file changed, 12 insertions(+), 18 deletions(-)

diff --git a/lxd/storage/drivers/utils.go b/lxd/storage/drivers/utils.go
index 7945ca3cde..3ff08a0de8 100644
--- a/lxd/storage/drivers/utils.go
+++ b/lxd/storage/drivers/utils.go
@@ -16,7 +16,6 @@ import (
        "github.com/lxc/lxd/lxd/operations"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/idmap"
-       "github.com/lxc/lxd/shared/units"
 )
 
 const minBlockBoundary = 8192
@@ -314,46 +313,41 @@ func createSparseFile(filePath string, sizeBytes int64) 
error {
 }
 
 // roundVolumeBlockFileSizeBytes parses the supplied size string and then 
rounds it to the nearest 8k bytes.
-func roundVolumeBlockFileSizeBytes(blockSize string) (int64, error) {
-       blockSizeBytes, err := units.ParseByteSizeString(blockSize)
-       if err != nil {
-               return -1, err
-       }
-
+func roundVolumeBlockFileSizeBytes(sizeBytes int64) (int64, error) {
        // Qemu requires image files to be in traditional storage block 
boundaries.
        // We use 8k here to ensure our images are compatible with all of our 
backend drivers.
-       if blockSizeBytes < minBlockBoundary {
-               blockSizeBytes = minBlockBoundary
+       if sizeBytes < minBlockBoundary {
+               sizeBytes = minBlockBoundary
        }
 
        // Round the size to closest minBlockBoundary bytes to avoid qemu 
boundary issues.
-       return int64(blockSizeBytes/minBlockBoundary) * minBlockBoundary, nil
+       return int64(sizeBytes/minBlockBoundary) * minBlockBoundary, nil
 }
 
 // ensureVolumeBlockFile creates or resizes the raw block file for a volume to 
the specified size.
-func ensureVolumeBlockFile(path, blockSize string) error {
-       if blockSize == "" {
-               blockSize = defaultBlockSize
+func ensureVolumeBlockFile(path string, sizeBytes int64) error {
+       if sizeBytes <= 0 {
+               return fmt.Errorf("Size cannot be zero")
        }
 
        // Get rounded block size to avoid qemu boundary issues.
-       blockSizeBytes, err := roundVolumeBlockFileSizeBytes(blockSize)
+       sizeBytes, err := roundVolumeBlockFileSizeBytes(sizeBytes)
        if err != nil {
                return err
        }
 
        if shared.PathExists(path) {
-               _, err = shared.RunCommand("qemu-img", "resize", "-f", "raw", 
path, fmt.Sprintf("%d", blockSizeBytes))
+               _, err = shared.RunCommand("qemu-img", "resize", "-f", "raw", 
path, fmt.Sprintf("%d", sizeBytes))
                if err != nil {
-                       return errors.Wrapf(err, "Failed resizing disk image %s 
to size %s", path, blockSize)
+                       return errors.Wrapf(err, "Failed resizing disk image %s 
to size %s", path, sizeBytes)
                }
        } else {
                // If path doesn't exist, then there has been no filler function
                // supplied to create it from another source. So instead create 
an empty
                // volume (use for PXE booting a VM).
-               _, err = shared.RunCommand("qemu-img", "create", "-f", "raw", 
path, fmt.Sprintf("%d", blockSizeBytes))
+               _, err = shared.RunCommand("qemu-img", "create", "-f", "raw", 
path, fmt.Sprintf("%d", sizeBytes))
                if err != nil {
-                       return errors.Wrapf(err, "Failed creating disk image %s 
as size %s", path, blockSize)
+                       return errors.Wrapf(err, "Failed creating disk image %s 
as size %s", path, sizeBytes)
                }
        }
 

From 0b1388432dcc310bcbe47f1e811d05de9f460edb Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:09:56 +0100
Subject: [PATCH 02/17] lxd/storage/drivers/generic/vfs: Updates
 genericVFSResizeBlockFile to accept size as bytes

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/generic_vfs.go | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lxd/storage/drivers/generic_vfs.go 
b/lxd/storage/drivers/generic_vfs.go
index 57ad06a62a..eaee1fb6df 100644
--- a/lxd/storage/drivers/generic_vfs.go
+++ b/lxd/storage/drivers/generic_vfs.go
@@ -779,8 +779,8 @@ func genericVFSBackupUnpack(d Driver, vol Volume, snapshots 
[]string, srcData io
 // genericVFSResizeBlockFile resizes an existing block file to the specified 
size. Returns true if resize took
 // place, false if not. Both requested size and existing file size are rounded 
to nearest block size using
 // roundVolumeBlockFileSizeBytes() before decision whether to resize is taken.
-func genericVFSResizeBlockFile(filePath, size string) (bool, error) {
-       if size == "" || size == "0" {
+func genericVFSResizeBlockFile(filePath string, sizeBytes int64) (bool, error) 
{
+       if sizeBytes <= 0 {
                return false, fmt.Errorf("Size cannot be zero")
        }
 
@@ -792,7 +792,7 @@ func genericVFSResizeBlockFile(filePath, size string) 
(bool, error) {
        oldSizeBytes := fi.Size()
 
        // Round the supplied size the same way the block files created are so 
its accurate comparison.
-       newSizeBytes, err := roundVolumeBlockFileSizeBytes(size)
+       newSizeBytes, err := roundVolumeBlockFileSizeBytes(sizeBytes)
        if err != nil {
                return false, err
        }
@@ -806,7 +806,7 @@ func genericVFSResizeBlockFile(filePath, size string) 
(bool, error) {
        }
 
        // Resize block file.
-       err = ensureVolumeBlockFile(filePath, size)
+       err = ensureVolumeBlockFile(filePath, sizeBytes)
        if err != nil {
                return false, err
        }

From 4d010d2f17c9e252da8a8ece24f175d1b76a3013 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:11:07 +0100
Subject: [PATCH 03/17] lxd/storage/drivers/driver/btrfs/utils: Adds volumeSize
 function

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_btrfs_utils.go | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/lxd/storage/drivers/driver_btrfs_utils.go 
b/lxd/storage/drivers/driver_btrfs_utils.go
index e097cfbd60..5b30f043c4 100644
--- a/lxd/storage/drivers/driver_btrfs_utils.go
+++ b/lxd/storage/drivers/driver_btrfs_utils.go
@@ -378,3 +378,15 @@ func (d *btrfs) receiveSubvolume(path string, targetPath 
string, conn io.ReadWri
 
        return nil
 }
+
+// volumeSize returns the size to use when creating new a volume.
+func (d *btrfs) volumeSize(vol Volume) string {
+       size := vol.ExpandedConfig("size")
+
+       // Block images always need a size.
+       if vol.contentType == ContentTypeBlock && (size == "" || size == "0") {
+               return defaultBlockSize
+       }
+
+       return size
+}

From cab52b86791eefc06cd91af211eb184d9278e0e3 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:12:14 +0100
Subject: [PATCH 04/17] lxd/storage/drivers/driver/btrfs/volumes: Updates
 CreateVolume to use volumeSize()

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_btrfs_volumes.go | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/lxd/storage/drivers/driver_btrfs_volumes.go 
b/lxd/storage/drivers/driver_btrfs_volumes.go
index a8ca986e9e..410e3d8ed5 100644
--- a/lxd/storage/drivers/driver_btrfs_volumes.go
+++ b/lxd/storage/drivers/driver_btrfs_volumes.go
@@ -60,7 +60,13 @@ func (d *btrfs) CreateVolume(vol Volume, filler 
*VolumeFiller, op *operations.Op
        // If we are creating a block volume, resize it to the requested size 
or the default.
        // We expect the filler function to have converted the qcow2 image to 
raw into the rootBlockPath.
        if vol.contentType == ContentTypeBlock {
-               err := ensureVolumeBlockFile(rootBlockPath, 
vol.ExpandedConfig("size"))
+               // Convert to bytes.
+               sizeBytes, err := units.ParseByteSizeString(d.volumeSize(vol))
+               if err != nil {
+                       return err
+               }
+
+               err = ensureVolumeBlockFile(rootBlockPath, sizeBytes)
                if err != nil {
                        return err
                }
@@ -74,7 +80,7 @@ func (d *btrfs) CreateVolume(vol Volume, filler 
*VolumeFiller, op *operations.Op
                }
        } else if vol.contentType == ContentTypeFS {
                // Set initial quota for filesystem volumes.
-               err := d.SetVolumeQuota(vol, vol.ExpandedConfig("size"), op)
+               err := d.SetVolumeQuota(vol, d.volumeSize(vol), op)
                if err != nil {
                        return err
                }
@@ -249,9 +255,9 @@ func (d *btrfs) CreateVolumeFromCopy(vol Volume, srcVol 
Volume, copySnapshots bo
        // This is so the pool default volume size isn't take into account for 
volume copies.
        volSize := vol.config["size"]
 
-       // If source is an image then use expanded config so that we take into 
account pool default volume size.
+       // If source is an image then take into account default volume sizes if 
not specified.
        if srcVol.volType == VolumeTypeImage {
-               volSize = vol.ExpandedConfig("size")
+               volSize = d.volumeSize(vol)
        }
 
        err = d.SetVolumeQuota(vol, volSize, op)

From 364fdfc9d317a36473e2ed45dd80aae9897c93f5 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:13:01 +0100
Subject: [PATCH 05/17] lxd/storage/drivers/driver/btrfs/volumes: Updates
 SetVolumeQuota to be byte oriented internally

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_btrfs_volumes.go | 25 +++++++++++----------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/lxd/storage/drivers/driver_btrfs_volumes.go 
b/lxd/storage/drivers/driver_btrfs_volumes.go
index 410e3d8ed5..9048a01f4c 100644
--- a/lxd/storage/drivers/driver_btrfs_volumes.go
+++ b/lxd/storage/drivers/driver_btrfs_volumes.go
@@ -449,20 +449,27 @@ func (d *btrfs) GetVolumeUsage(vol Volume) (int64, error) 
{
 }
 
 // SetVolumeQuota sets the quota on the volume.
+// Does nothing if supplied with an empty/zero size for block volumes, and for 
filesystem volumes removes quota.
 func (d *btrfs) SetVolumeQuota(vol Volume, size string, op 
*operations.Operation) error {
+       // Convert to bytes.
+       sizeBytes, err := units.ParseByteSizeString(size)
+       if err != nil {
+               return err
+       }
+
        // For VM block files, resize the file if needed.
        if vol.contentType == ContentTypeBlock {
+               // Do nothing if size isn't specified.
+               if sizeBytes <= 0 {
+                       return nil
+               }
+
                rootBlockPath, err := d.GetVolumeDiskPath(vol)
                if err != nil {
                        return err
                }
 
-               // If size not specified in volume config, then use pool's 
default block size.
-               if size == "" || size == "0" {
-                       size = defaultBlockSize
-               }
-
-               resized, err := genericVFSResizeBlockFile(rootBlockPath, size)
+               resized, err := genericVFSResizeBlockFile(rootBlockPath, 
sizeBytes)
                if err != nil {
                        return err
                }
@@ -483,12 +490,6 @@ func (d *btrfs) SetVolumeQuota(vol Volume, size string, op 
*operations.Operation
        // For non-VM block volumes, set filesystem quota.
        volPath := vol.MountPath()
 
-       // Convert to bytes.
-       sizeBytes, err := units.ParseByteSizeString(size)
-       if err != nil {
-               return err
-       }
-
        // Try to locate an existing quota group.
        qgroup, _, err := d.getQGroup(volPath)
        if err != nil && !d.state.OS.RunningInUserNS {

From 84c7ad8eb7ff0fd54fcafcfeb4969d6ac1fdca5d Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:13:32 +0100
Subject: [PATCH 06/17] lxd/storage/drivers/driver/ceph/utils: Updates
 volumeSize comment for consistency

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_ceph_utils.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lxd/storage/drivers/driver_ceph_utils.go 
b/lxd/storage/drivers/driver_ceph_utils.go
index e9abe379c6..47ebdb1be2 100644
--- a/lxd/storage/drivers/driver_ceph_utils.go
+++ b/lxd/storage/drivers/driver_ceph_utils.go
@@ -529,7 +529,7 @@ func (d *ceph) rbdListVolumeSnapshots(vol Volume) 
([]string, error) {
        return snapshots, nil
 }
 
-// volumeSize returns the size to use when creating new RBD volumes.
+// volumeSize returns the size to use when creating new a volume.
 func (d *ceph) volumeSize(vol Volume) string {
        size := vol.ExpandedConfig("size")
        if size == "" || size == "0" {

From 41a4b25c88cbc83b4229994573a08dfeff120fad Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:14:07 +0100
Subject: [PATCH 07/17] lxd/storage/drivers/driver/ceph/volumes: Updates
 CreateVolumeFromCopy to use volumeSize()

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_ceph_volumes.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lxd/storage/drivers/driver_ceph_volumes.go 
b/lxd/storage/drivers/driver_ceph_volumes.go
index ece231b52b..11bf747c5e 100644
--- a/lxd/storage/drivers/driver_ceph_volumes.go
+++ b/lxd/storage/drivers/driver_ceph_volumes.go
@@ -313,9 +313,9 @@ func (d *ceph) CreateVolumeFromCopy(vol Volume, srcVol 
Volume, copySnapshots boo
                // This is so the pool default volume size isn't take into 
account for volume copies.
                volSize := vol.config["size"]
 
-               // If source is an image then use expanded config so that we 
take into account pool volume size.
+               // If source is an image then take into account default volume 
sizes if not specified.
                if srcVol.volType == VolumeTypeImage {
-                       volSize = vol.ExpandedConfig("size")
+                       volSize = d.volumeSize(vol)
                }
 
                err = d.SetVolumeQuota(vol, volSize, op)

From 2bcc5a053f0e9cfbcddfda6d3d27eb107f57489c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:14:39 +0100
Subject: [PATCH 08/17] lxd/storage/drivers/driver/ceph/volumes: Updates
 SetVolumeQuota to be byte oriented internally

Also renames newSizeBytes to sizeBytes for consistency with other driver's 
SetVolumeQuota function.

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_ceph_volumes.go | 30 +++++++++++++---------
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/lxd/storage/drivers/driver_ceph_volumes.go 
b/lxd/storage/drivers/driver_ceph_volumes.go
index 11bf747c5e..53521927ff 100644
--- a/lxd/storage/drivers/driver_ceph_volumes.go
+++ b/lxd/storage/drivers/driver_ceph_volumes.go
@@ -802,7 +802,19 @@ func (d *ceph) GetVolumeUsage(vol Volume) (int64, error) {
 }
 
 // SetVolumeQuota applies a size limit on volume.
+// Does nothing if supplied with an empty/zero size.
 func (d *ceph) SetVolumeQuota(vol Volume, size string, op 
*operations.Operation) error {
+       // Convert to bytes.
+       sizeBytes, err := units.ParseByteSizeString(size)
+       if err != nil {
+               return err
+       }
+
+       // Do nothing if size isn't specified.
+       if sizeBytes <= 0 {
+               return nil
+       }
+
        fsType := d.getRBDFilesystem(vol)
 
        RBDDevPath, err := d.getRBDMappedDevPath(vol)
@@ -822,26 +834,20 @@ func (d *ceph) SetVolumeQuota(vol Volume, size string, op 
*operations.Operation)
                return errors.Wrapf(err, "Error getting current size")
        }
 
-       newSizeBytes, err := units.ParseByteSizeString(size)
-       if err != nil {
-               return err
-       }
-
-       // The right disjunct just means that someone unset the size property 
in the instance's config.
-       // We obviously cannot resize to 0.
-       if oldSizeBytes == newSizeBytes || newSizeBytes == 0 {
+       // Do nothing is volume is already specified size.
+       if oldSizeBytes == sizeBytes {
                return nil
        }
 
        // Resize filesystem if needed.
-       if newSizeBytes < oldSizeBytes {
+       if sizeBytes < oldSizeBytes {
                if vol.contentType == ContentTypeBlock && 
!vol.allowUnsafeResize {
                        return errors.Wrap(ErrCannotBeShrunk, "You cannot 
shrink block volumes")
                }
 
                // Shrink the filesystem.
                if vol.contentType == ContentTypeFS {
-                       err = shrinkFileSystem(fsType, RBDDevPath, vol, 
newSizeBytes)
+                       err = shrinkFileSystem(fsType, RBDDevPath, vol, 
sizeBytes)
                        if err != nil {
                                return err
                        }
@@ -855,7 +861,7 @@ func (d *ceph) SetVolumeQuota(vol Volume, size string, op 
*operations.Operation)
                        "--id", d.config["ceph.user.name"],
                        "--cluster", d.config["ceph.cluster_name"],
                        "--pool", d.config["ceph.osd.pool_name"],
-                       "--size", fmt.Sprintf("%dB", newSizeBytes),
+                       "--size", fmt.Sprintf("%dB", sizeBytes),
                        d.getRBDVolumeName(vol, "", false, false))
                if err != nil {
                        return err
@@ -868,7 +874,7 @@ func (d *ceph) SetVolumeQuota(vol Volume, size string, op 
*operations.Operation)
                        "--id", d.config["ceph.user.name"],
                        "--cluster", d.config["ceph.cluster_name"],
                        "--pool", d.config["ceph.osd.pool_name"],
-                       "--size", fmt.Sprintf("%dB", newSizeBytes),
+                       "--size", fmt.Sprintf("%dB", sizeBytes),
                        d.getRBDVolumeName(vol, "", false, false))
                if err != nil {
                        return err

From efb41dd08fd751841498d02607ecb7f72a761ac0 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:15:44 +0100
Subject: [PATCH 09/17] lxd/storage/drivers/driver/dir/utils: Adds volumeSize
 function

And updates setupInitialQuota to use it.

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_dir_utils.go | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/lxd/storage/drivers/driver_dir_utils.go 
b/lxd/storage/drivers/driver_dir_utils.go
index 4ca5e3035e..ba9bd00d2f 100644
--- a/lxd/storage/drivers/driver_dir_utils.go
+++ b/lxd/storage/drivers/driver_dir_utils.go
@@ -48,7 +48,7 @@ func (d *dir) setupInitialQuota(vol Volume) (func(), error) {
        revert.Add(revertFunc)
 
        // Set the quota.
-       err = d.setQuota(volPath, volID, vol.ExpandedConfig("size"))
+       err = d.setQuota(volPath, volID, d.volumeSize(vol))
        if err != nil {
                return nil, err
        }
@@ -149,3 +149,15 @@ func (d *dir) setQuota(path string, volID int64, size 
string) error {
 
        return quota.SetProjectQuota(path, d.quotaProjectID(volID), sizeBytes)
 }
+
+// volumeSize returns the size to use when creating new a volume.
+func (d *dir) volumeSize(vol Volume) string {
+       size := vol.ExpandedConfig("size")
+
+       // Block images always need a size.
+       if vol.contentType == ContentTypeBlock && (size == "" || size == "0") {
+               return defaultBlockSize
+       }
+
+       return size
+}

From 6e8fb93fa9fd6ca316ea37808bad8070b2302773 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:16:48 +0100
Subject: [PATCH 10/17] lxd/storage/drivers/driver/dir/volumes: Updates
 CreateVolume to use volumeSize

And updates usage of genericVFSResizeBlockFile.

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_dir_volumes.go | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/lxd/storage/drivers/driver_dir_volumes.go 
b/lxd/storage/drivers/driver_dir_volumes.go
index 58b1d0b157..e850c8b344 100644
--- a/lxd/storage/drivers/driver_dir_volumes.go
+++ b/lxd/storage/drivers/driver_dir_volumes.go
@@ -15,6 +15,7 @@ import (
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/instancewriter"
        log "github.com/lxc/lxd/shared/log15"
+       "github.com/lxc/lxd/shared/units"
 )
 
 // CreateVolume creates an empty volume and can optionally fill it by 
executing the supplied
@@ -64,7 +65,13 @@ func (d *dir) CreateVolume(vol Volume, filler *VolumeFiller, 
op *operations.Oper
        // If we are creating a block volume, resize it to the requested size 
or the default.
        // We expect the filler function to have converted the qcow2 image to 
raw into the rootBlockPath.
        if vol.contentType == ContentTypeBlock {
-               err := ensureVolumeBlockFile(rootBlockPath, 
vol.ExpandedConfig("size"))
+               // Convert to bytes.
+               sizeBytes, err := units.ParseByteSizeString(d.volumeSize(vol))
+               if err != nil {
+                       return err
+               }
+
+               err = ensureVolumeBlockFile(rootBlockPath, sizeBytes)
                if err != nil {
                        return err
                }

From 6c1b4c6ba7230df553f861833061374848211d7c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:17:32 +0100
Subject: [PATCH 11/17] lxd/storage/drivers/driver/dir/volumes: Updates
 SetVolumeQuota to be byte oriented internally

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_dir_volumes.go | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/lxd/storage/drivers/driver_dir_volumes.go 
b/lxd/storage/drivers/driver_dir_volumes.go
index e850c8b344..61a8516080 100644
--- a/lxd/storage/drivers/driver_dir_volumes.go
+++ b/lxd/storage/drivers/driver_dir_volumes.go
@@ -249,20 +249,27 @@ func (d *dir) GetVolumeUsage(vol Volume) (int64, error) {
 }
 
 // SetVolumeQuota sets the quota on the volume.
+// Does nothing if supplied with an empty/zero size for block volumes, and for 
filesystem volumes removes quota.
 func (d *dir) SetVolumeQuota(vol Volume, size string, op 
*operations.Operation) error {
+       // Convert to bytes.
+       sizeBytes, err := units.ParseByteSizeString(size)
+       if err != nil {
+               return err
+       }
+
        // For VM block files, resize the file if needed.
        if vol.contentType == ContentTypeBlock {
+               // Do nothing if size isn't specified.
+               if sizeBytes <= 0 {
+                       return nil
+               }
+
                rootBlockPath, err := d.GetVolumeDiskPath(vol)
                if err != nil {
                        return err
                }
 
-               // If size not specified in volume config, then use pool's 
default block size.
-               if size == "" || size == "0" {
-                       size = defaultBlockSize
-               }
-
-               resized, err := genericVFSResizeBlockFile(rootBlockPath, size)
+               resized, err := genericVFSResizeBlockFile(rootBlockPath, 
sizeBytes)
                if err != nil {
                        return err
                }

From fd989192783ec09ec78b6575d850f93dea1b6bac Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:18:59 +0100
Subject: [PATCH 12/17] lxd/storage/drivers/driver/lvm/utils: Updates
 copyThinpoolVolume to use volumeSize()

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_lvm_utils.go | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lxd/storage/drivers/driver_lvm_utils.go 
b/lxd/storage/drivers/driver_lvm_utils.go
index 37f914be05..4c6f543528 100644
--- a/lxd/storage/drivers/driver_lvm_utils.go
+++ b/lxd/storage/drivers/driver_lvm_utils.go
@@ -54,7 +54,7 @@ func (d *lvm) volumeFilesystem(vol Volume) string {
        return DefaultFilesystem
 }
 
-// volumeSize returns the size to use when creating new logical volumes.
+// volumeSize returns the size to use when creating new a volume.
 func (d *lvm) volumeSize(vol Volume) string {
        size := vol.ExpandedConfig("size")
        if size == "" || size == "0" {
@@ -654,9 +654,9 @@ func (d *lvm) copyThinpoolVolume(vol, srcVol Volume, 
srcSnapshots []Volume, refr
        // This is so the pool default volume size isn't take into account for 
volume copies.
        volSize := vol.config["size"]
 
-       // If source is an image then use expanded config so that we take into 
account pool default volume size.
+       // If source is an image then take into account default volume sizes if 
not specified.
        if srcVol.volType == VolumeTypeImage {
-               volSize = vol.ExpandedConfig("size")
+               volSize = d.volumeSize(vol)
        }
 
        err = d.SetVolumeQuota(vol, volSize, nil)

From 458aa8005a652f0419ca25bd4b4578e305ab2724 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:19:54 +0100
Subject: [PATCH 13/17] lxd/storage/drivers/driver/lvm/volumes: Updates
 SetVolumeQuota variables and comments

For consistency with other drivers.

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_lvm_volumes.go | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/lxd/storage/drivers/driver_lvm_volumes.go 
b/lxd/storage/drivers/driver_lvm_volumes.go
index 62ef87fc49..a001ba1561 100644
--- a/lxd/storage/drivers/driver_lvm_volumes.go
+++ b/lxd/storage/drivers/driver_lvm_volumes.go
@@ -316,13 +316,14 @@ func (d *lvm) GetVolumeUsage(vol Volume) (int64, error) {
 }
 
 // SetVolumeQuota sets the quota on the volume.
+// Does nothing if supplied with an empty/zero size.
 func (d *lvm) SetVolumeQuota(vol Volume, size string, op 
*operations.Operation) error {
-       // Can't do anything if the size property has been removed from volume 
config.
+       // Do nothing if size isn't specified.
        if size == "" || size == "0" {
                return nil
        }
 
-       newSizeBytes, err := d.roundedSizeBytesString(size)
+       sizeBytes, err := d.roundedSizeBytesString(size)
        if err != nil {
                return err
        }
@@ -342,7 +343,7 @@ func (d *lvm) SetVolumeQuota(vol Volume, size string, op 
*operations.Operation)
        }
 
        // Round up the number of extents required for new quota size, as this 
is what the lvresize tool will do.
-       newNumExtents := math.Ceil(float64(newSizeBytes) / 
float64(vgExtentSize))
+       newNumExtents := math.Ceil(float64(sizeBytes) / float64(vgExtentSize))
        oldNumExtents := math.Ceil(float64(oldSizeBytes) / 
float64(vgExtentSize))
        extentDiff := int(newNumExtents - oldNumExtents)
 
@@ -351,25 +352,25 @@ func (d *lvm) SetVolumeQuota(vol Volume, size string, op 
*operations.Operation)
                return nil
        }
 
-       logCtx := log.Ctx{"dev": volDevPath, "size": fmt.Sprintf("%db", 
newSizeBytes)}
+       logCtx := log.Ctx{"dev": volDevPath, "size": fmt.Sprintf("%db", 
sizeBytes)}
 
        // Resize filesystem if needed.
        if vol.contentType == ContentTypeFS {
-               if newSizeBytes < oldSizeBytes {
+               if sizeBytes < oldSizeBytes {
                        // Shrink filesystem to new size first, then shrink 
logical volume.
-                       err = shrinkFileSystem(d.volumeFilesystem(vol), 
volDevPath, vol, newSizeBytes)
+                       err = shrinkFileSystem(d.volumeFilesystem(vol), 
volDevPath, vol, sizeBytes)
                        if err != nil {
                                return err
                        }
                        d.logger.Debug("Logical volume filesystem shrunk", 
logCtx)
 
-                       err = d.resizeLogicalVolume(volDevPath, newSizeBytes)
+                       err = d.resizeLogicalVolume(volDevPath, sizeBytes)
                        if err != nil {
                                return err
                        }
-               } else if newSizeBytes > oldSizeBytes {
+               } else if sizeBytes > oldSizeBytes {
                        // Grow logical volume to new size first, then grow 
filesystem to fill it.
-                       err = d.resizeLogicalVolume(volDevPath, newSizeBytes)
+                       err = d.resizeLogicalVolume(volDevPath, sizeBytes)
                        if err != nil {
                                return err
                        }
@@ -381,11 +382,11 @@ func (d *lvm) SetVolumeQuota(vol Volume, size string, op 
*operations.Operation)
                        d.logger.Debug("Logical volume filesystem grown", 
logCtx)
                }
        } else {
-               if newSizeBytes < oldSizeBytes && !vol.allowUnsafeResize {
+               if sizeBytes < oldSizeBytes && !vol.allowUnsafeResize {
                        return errors.Wrap(ErrCannotBeShrunk, "You cannot 
shrink block volumes")
                }
 
-               err = d.resizeLogicalVolume(volDevPath, newSizeBytes)
+               err = d.resizeLogicalVolume(volDevPath, sizeBytes)
                if err != nil {
                        return err
 

From e9b0e7d7f8982c5194c3003d7ebd9cfd9a751035 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:20:24 +0100
Subject: [PATCH 14/17] lxd/storage/drivers/driver/zfs/utils: Adds volumeSize
 function

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_zfs_utils.go | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/lxd/storage/drivers/driver_zfs_utils.go 
b/lxd/storage/drivers/driver_zfs_utils.go
index 9cdd6c127e..caa92148ab 100644
--- a/lxd/storage/drivers/driver_zfs_utils.go
+++ b/lxd/storage/drivers/driver_zfs_utils.go
@@ -316,3 +316,15 @@ func (d *zfs) receiveDataset(dataset string, conn 
io.ReadWriteCloser, writeWrapp
 
        return nil
 }
+
+// volumeSize returns the size to use when creating new a volume.
+func (d *zfs) volumeSize(vol Volume) string {
+       size := vol.ExpandedConfig("size")
+
+       // Block images always need a size.
+       if vol.contentType == ContentTypeBlock && (size == "" || size == "0") {
+               return defaultBlockSize
+       }
+
+       return size
+}

From 154734d47e9756224300e27ae179a2b6c4f8e6d2 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:20:57 +0100
Subject: [PATCH 15/17] lxd/storage/drivers/driver/zfs/volumes: Updates
 CreateVolume to use volumeSize()

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_zfs_volumes.go | 17 ++++-------------
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/lxd/storage/drivers/driver_zfs_volumes.go 
b/lxd/storage/drivers/driver_zfs_volumes.go
index bf75224da0..52cd8d54ed 100644
--- a/lxd/storage/drivers/driver_zfs_volumes.go
+++ b/lxd/storage/drivers/driver_zfs_volumes.go
@@ -133,21 +133,12 @@ func (d *zfs) CreateVolume(vol Volume, filler 
*VolumeFiller, op *operations.Oper
                }
 
                // Apply the size limit.
-               size := vol.ExpandedConfig("size")
-               if size != "" {
-                       err := d.SetVolumeQuota(vol, size, op)
-                       if err != nil {
-                               return err
-                       }
+               err = d.SetVolumeQuota(vol, d.volumeSize(vol), op)
+               if err != nil {
+                       return err
                }
        } else {
-               // Convert the size.
-               size := vol.ExpandedConfig("size")
-               if size == "" {
-                       size = defaultBlockSize
-               }
-
-               sizeBytes, err := units.ParseByteSizeString(size)
+               sizeBytes, err := units.ParseByteSizeString(d.volumeSize(vol))
                if err != nil {
                        return err
                }

From abf50f877f89522519b08d0fe2513463dd67db4b Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:21:23 +0100
Subject: [PATCH 16/17] lxd/storage/drivers/driver/zfs/volumes: Updates
 CreateVolumeFromCopy to use volumeSize()

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_zfs_volumes.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lxd/storage/drivers/driver_zfs_volumes.go 
b/lxd/storage/drivers/driver_zfs_volumes.go
index 52cd8d54ed..ea14fa6db8 100644
--- a/lxd/storage/drivers/driver_zfs_volumes.go
+++ b/lxd/storage/drivers/driver_zfs_volumes.go
@@ -590,9 +590,9 @@ func (d *zfs) CreateVolumeFromCopy(vol Volume, srcVol 
Volume, copySnapshots bool
        // This is so the pool default volume size isn't take into account for 
volume copies.
        volSize := vol.config["size"]
 
-       // If source is an image then use expanded config so that we take into 
account pool default volume size.
+       // If source is an image then take into account default volume sizes if 
not specified.
        if srcVol.volType == VolumeTypeImage {
-               volSize = vol.ExpandedConfig("size")
+               volSize = d.volumeSize(vol)
        }
 
        err := d.SetVolumeQuota(vol, volSize, op)

From 12988d6143409d8095748f5b9a08e8eedc0a5982 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 1 May 2020 11:21:43 +0100
Subject: [PATCH 17/17] lxd/storage/drivers/driver/zfs/volumes: Updates
 SetVolumeQuota to be byte oriented internally

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/storage/drivers/driver_zfs_volumes.go | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/lxd/storage/drivers/driver_zfs_volumes.go 
b/lxd/storage/drivers/driver_zfs_volumes.go
index ea14fa6db8..b9f88d13d8 100644
--- a/lxd/storage/drivers/driver_zfs_volumes.go
+++ b/lxd/storage/drivers/driver_zfs_volumes.go
@@ -879,15 +879,9 @@ func (d *zfs) GetVolumeUsage(vol Volume) (int64, error) {
        return valueInt, nil
 }
 
+// SetVolumeQuota sets the quota on the volume.
+// Does nothing if supplied with an empty/zero size for block volumes, and for 
filesystem volumes removes quota.
 func (d *zfs) SetVolumeQuota(vol Volume, size string, op 
*operations.Operation) error {
-       if size == "" || size == "0" {
-               if vol.contentType == ContentTypeBlock {
-                       size = defaultBlockSize
-               } else {
-                       size = "0"
-               }
-       }
-
        // Convert to bytes.
        sizeBytes, err := units.ParseByteSizeString(size)
        if err != nil {
@@ -896,6 +890,11 @@ func (d *zfs) SetVolumeQuota(vol Volume, size string, op 
*operations.Operation)
 
        // Handle volume datasets.
        if vol.contentType == ContentTypeBlock {
+               // Do nothing if size isn't specified.
+               if sizeBytes <= 0 {
+                       return nil
+               }
+
                sizeBytes = (sizeBytes / minBlockBoundary) * minBlockBoundary
 
                oldSizeBytesStr, err := d.getDatasetProperty(d.dataset(vol, 
false), "volsize")
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to