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