The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/3705
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) === Signed-off-by: Christian Brauner <[email protected]>
From 0e6f72aced5a18d7e90a520d76e33425eb41c6fd Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Tue, 22 Aug 2017 16:37:19 +0200 Subject: [PATCH 1/2] zfs: apply quota on container creation Signed-off-by: Christian Brauner <[email protected]> --- lxd/storage_zfs.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go index 61b829e96..de61d6c43 100644 --- a/lxd/storage_zfs.go +++ b/lxd/storage_zfs.go @@ -760,6 +760,19 @@ func (s *storageZfs) ContainerCreate(container container) error { defer s.ContainerUmount(containerName, containerPath) } + // apply quota + if s.volume.Config["size"] != "" { + size, err := shared.ParseByteSizeString(s.volume.Config["size"]) + if err != nil { + return err + } + + err = s.StorageEntitySetQuota(storagePoolVolumeTypeContainer, size, container) + if err != nil { + return err + } + } + err = createContainerMountpoint(containerPoolVolumeMntPoint, containerPath, container.IsPrivileged()) if err != nil { return err @@ -836,6 +849,19 @@ func (s *storageZfs) ContainerCreateFromImage(container container, fingerprint s defer s.ContainerUmount(containerName, containerPath) } + // apply quota + if s.volume.Config["size"] != "" { + size, err := shared.ParseByteSizeString(s.volume.Config["size"]) + if err != nil { + return err + } + + err = s.StorageEntitySetQuota(storagePoolVolumeTypeContainer, size, container) + if err != nil { + return err + } + } + privileged := container.IsPrivileged() err = createContainerMountpoint(containerPoolVolumeMntPoint, containerPath, privileged) if err != nil { From 14b57e8bb3441abeb8d62e00eeb412e7d55e7b7f Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Tue, 22 Aug 2017 16:37:38 +0200 Subject: [PATCH 2/2] zfs: allow to change "volume.size" property The logic here is: - Profile beats Pool: If the container has a "size" property set on a root disk device it has in its local devices or inherits from a profile then the "volume.size" property from the pool will not be applied. - Volume beats Pool: If the storage volume has a "size" property applied then the "volume.size" property from the pool will not be applied. Signed-off-by: Christian Brauner <[email protected]> --- lxd/container.go | 4 +-- lxd/storage_pools_config.go | 8 ++++- lxd/storage_volumes_config.go | 5 ++++ lxd/storage_zfs.go | 68 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/lxd/container.go b/lxd/container.go index 39be1d83f..426e41d2c 100644 --- a/lxd/container.go +++ b/lxd/container.go @@ -488,9 +488,9 @@ type container interface { StoragePool() (string, error) - // FIXME: Those should be internal functions - // Needed for migration for now. StorageStart() (bool, error) + // Kill this function as soon as zfs is fixed. + StorageStartSensitive() (bool, error) StorageStop() (bool, error) Storage() storage IdmapSet() (*shared.IdmapSet, error) diff --git a/lxd/storage_pools_config.go b/lxd/storage_pools_config.go index cc429186a..785e28942 100644 --- a/lxd/storage_pools_config.go +++ b/lxd/storage_pools_config.go @@ -122,7 +122,13 @@ func storagePoolValidateConfig(name string, driver string, config map[string]str } if driver != "lvm" && driver != "ceph" { - if prfx(key, "lvm.") || prfx(key, "volume.block.") || key == "volume.size" { + if prfx(key, "lvm.") || prfx(key, "volume.block.") { + return fmt.Errorf("the key %s cannot be used with %s storage pools", key, strings.ToUpper(driver)) + } + } + + if driver != "lvm" && driver != "ceph" && driver != "zfs" { + if key == "volume.size" { return fmt.Errorf("the key %s cannot be used with %s storage pools", key, strings.ToUpper(driver)) } } diff --git a/lxd/storage_volumes_config.go b/lxd/storage_volumes_config.go index 37ac53877..9e94083e4 100644 --- a/lxd/storage_volumes_config.go +++ b/lxd/storage_volumes_config.go @@ -103,6 +103,11 @@ func storageVolumeFillDefault(name string, config map[string]string, parentPool config["size"] = "10GB" } } else { + // Does the pool request a default size for new storage volumes? + if config["size"] == "0" || config["size"] == "" { + config["size"] = parentPool.Config["volume.size"] + } + if config["size"] != "" { _, err := shared.ParseByteSizeString(config["size"]) if err != nil { diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go index de61d6c43..4ccb99f48 100644 --- a/lxd/storage_zfs.go +++ b/lxd/storage_zfs.go @@ -547,7 +547,73 @@ func (s *storageZfs) StoragePoolUpdate(writable *api.StoragePoolPut, changedConf } if shared.StringInSlice("volume.size", changedConfig) { - return fmt.Errorf("the \"volume.size\" property cannot be changed") + volumes, err := db.StoragePoolVolumesGet(s.d.db, s.poolID, + []int{storagePoolVolumeTypeContainer}) + if err != nil { + if err != db.NoSuchObjectError { + return err + } + } + + // The name of a container is always identical to the name of + // its storage volume. + for _, volume := range volumes { + ct, err := containerLoadByName(s.d, volume.Name) + if err != nil { + return err + } + + // Quota do not apply to snapshots (I *think*.) + if ct.IsSnapshot() { + continue + } + + // Check if the storage volume itself already has local + // "size" property set. + if volume.Config["size"] != "" { + continue + } + + // Check if the container has a "size" property set on + // its root disk device in its local devices. + localDevices := ct.LocalDevices() + _, rootDiskDevice, _ := containerGetRootDiskDevice(localDevices) + // Check if the container inherits a "size" property + // from a root disk device in one of its profiles. + if rootDiskDevice["size"] == "" { + expandedDevices := ct.ExpandedDevices() + _, rootDiskDevice, _ = containerGetRootDiskDevice(expandedDevices) + } + + // Non-storage pool "size" properties override storage + // pool "size" properties + if rootDiskDevice["size"] != "" { + continue + } + + ourStart, err := ct.StorageStartSensitive() + if err != nil { + return err + } + if ourStart { + defer ct.StorageStop() + } + + size := int64(0) + if writable.Config["volume.size"] != "" { + size, err = shared.ParseByteSizeString(writable.Config["volume.size"]) + if err != nil { + return err + } + } + + st := ct.Storage() + err = st.StorageEntitySetQuota(storagePoolVolumeTypeContainer, + size, ct) + if err != nil { + return err + } + } } if shared.StringInSlice("volume.block.mount_options", changedConfig) {
_______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
