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

Reply via email to