[lxc-devel] [lxd/master] zfs: enable volume.size property
brauner on Github
lxc-bot at linuxcontainers.org
Tue Aug 22 14:44:08 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 364 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170822/b9577878/attachment.bin>
-------------- next part --------------
From 0e6f72aced5a18d7e90a520d76e33425eb41c6fd Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 22 Aug 2017 16:37:19 +0200
Subject: [PATCH 1/2] zfs: apply quota on container creation
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
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 <christian.brauner at ubuntu.com>
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 <christian.brauner at ubuntu.com>
---
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) {
More information about the lxc-devel
mailing list