[lxc-devel] [lxd/master] Support disk limits in projects
freeekanayaka on Github
lxc-bot at linuxcontainers.org
Tue Jul 14 12:48:12 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200714/7725da7f/attachment.bin>
-------------- next part --------------
From 5b5df83d8b462d077436daba1757d345ac8d26a3 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Tue, 14 Jul 2020 10:56:28 +0200
Subject: [PATCH 1/6] lxd/db: Drive-by removal of leftover fmt.Printf's
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
lxd/db/node.go | 3 ---
1 file changed, 3 deletions(-)
diff --git a/lxd/db/node.go b/lxd/db/node.go
index 51628cad1c..ceb2ee2b8c 100644
--- a/lxd/db/node.go
+++ b/lxd/db/node.go
@@ -786,16 +786,13 @@ func (c *ClusterTx) GetNodeWithLeastInstances(archs []int) (string, error) {
supported = append(supported, personalities...)
match := false
- fmt.Printf("stgraber: supported=%v requested=%v\n", supported, archs)
for _, entry := range supported {
if shared.IntInSlice(entry, archs) {
- fmt.Printf("stgraber: supported\n")
match = true
}
}
if !match {
- fmt.Printf("stgraber: unsupported\n")
continue
}
}
From 22fae6f11d9248c8b54dfc2150b18df39caf2d5a Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Tue, 14 Jul 2020 12:29:38 +0200
Subject: [PATCH 2/6] shared/version: Add projects_limits_disk extension
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
doc/api-extensions.md | 5 +++++
shared/version/api.go | 1 +
2 files changed, 6 insertions(+)
diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 1a2b81ed67..5a568ee74a 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -1118,3 +1118,8 @@ be set to `console` (default) or `vga` (the new type added by this extension).
When POST'ing to `/1.0/<instance name>/console?type=vga` the data websocket
returned by the operation in the metadata field will be a bidirectional proxy
attached to a SPICE unix socket of the target virtual machine.
+
+## projects\_limits\_disk
+Add `limits.disk` to the available project configuration keys. If set, it limits
+the total amount of disk space that instances volumes, custom volumes and images
+volumes can use in the project.
diff --git a/shared/version/api.go b/shared/version/api.go
index 8fb696c459..43931942bc 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -219,6 +219,7 @@ var APIExtensions = []string{
"clustering_failure_domains",
"resources_gpu_mdev",
"console_vga_type",
+ "projects_limits_disk",
}
// APIExtensionsCount returns the number of available API extensions.
From f3cdbb42f009e1b81aa68aede01afc3e6cf14150 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Tue, 14 Jul 2020 12:38:45 +0200
Subject: [PATCH 3/6] doc: Document limits.disk project configuration key
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
doc/projects.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/doc/projects.md b/doc/projects.md
index 18f225728b..882592db65 100644
--- a/doc/projects.md
+++ b/doc/projects.md
@@ -23,7 +23,8 @@ features.storage.volumes | boolean | - | true
limits.containers | integer | - | - | Maximum number of containers that can be created in the project
limits.virtual-machines | integer | - | - | Maximum number of VMs that can be created in the project
limits.cpu | integer | - | - | Maximum value for the sum of individual "limits.cpu" configs set on the instances of the project
-limits.memory | integer | - | - | Maximum value for the sum of individual "limits.memory" configs set on the instances of the project
+limits.disk | string | - | - | Maximum value for the sum of individual "limits.memory" configs set on the instances of the project
+limits.memory | string | - | - | Maximum value of aggregate disk space used by all instances volumes, custom volumes and images of the project
limits.processes | integer | - | - | Maximum value for the sum of individual "limits.processes" configs set on the instances of the project
restricted | boolean | - | true | Block access to security-sensitive features
restricted.containers.nesting | string | - | block | Prevents setting security.nesting=true.
From a8efb7fc1698c916d42b39f0b9b2f81b7b064caf Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Tue, 14 Jul 2020 12:39:17 +0200
Subject: [PATCH 4/6] lxd: Add "limits.disk" to supported project config keys
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
lxd/api_project.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/lxd/api_project.go b/lxd/api_project.go
index 5a95f71ab5..4e336fd7ed 100644
--- a/lxd/api_project.go
+++ b/lxd/api_project.go
@@ -530,6 +530,7 @@ var projectConfigKeys = map[string]func(value string) error{
"limits.memory": shared.IsSize,
"limits.processes": shared.IsUint32,
"limits.cpu": shared.IsUint32,
+ "limits.disk": shared.IsSize,
"restricted": shared.IsBool,
"restricted.containers.nesting": isEitherAllowOrBlock,
"restricted.containers.lowlevel": isEitherAllowOrBlock,
From e35dd7ccb1559ed9569fb249037ddf33e4195d9f Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Tue, 14 Jul 2020 14:45:38 +0200
Subject: [PATCH 5/6] lxd/project: Check that root disk sizes are within
limits.disk
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
lxd/project/permissions.go | 38 +++++++++++++++++++++++++++++++++-----
1 file changed, 33 insertions(+), 5 deletions(-)
diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index dbc5ce801d..30402a5d0e 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -418,6 +418,7 @@ func checkRestrictions(project *api.Project, instances []db.Instance, profiles [
var allAggregateLimits = []string{
"limits.cpu",
+ "limits.disk",
"limits.memory",
"limits.processes",
}
@@ -599,6 +600,8 @@ func AllowProjectUpdate(tx *db.ClusterTx, projectName string, config map[string]
case "limits.cpu":
fallthrough
case "limits.memory":
+ fallthrough
+ case "limits.disk":
aggregateKeys = append(aggregateKeys, key)
}
@@ -785,11 +788,30 @@ func getInstanceLimits(instance db.Instance, keys []string) (map[string]int64, e
limits := map[string]int64{}
for _, key := range keys {
- value, ok := instance.Config[key]
- if !ok || value == "" {
- return nil, fmt.Errorf(
- "Instance %s in project %s has no '%s' config, either directly or via a profile",
- instance.Name, instance.Project, key)
+ var value string
+ var ok bool
+ if key == "limits.disk" {
+ _, device, err := shared.GetRootDiskDevice(instance.Devices)
+ if err != nil {
+ return nil, fmt.Errorf(
+ "Instance %s in project %s has no root device",
+ instance.Name, instance.Project)
+ }
+ value, ok = device["size"]
+ if !ok || value == "" {
+ return nil, fmt.Errorf(
+ "Instance %s in project %s has no 'size' config set on the root device, "+
+ "either directly or via a profile",
+ instance.Name, instance.Project)
+ }
+ } else {
+ value, ok = instance.Config[key]
+ if !ok || value == "" {
+ return nil, fmt.Errorf(
+ "Instance %s in project %s has no '%s' config, "+
+ "either directly or via a profile",
+ instance.Name, instance.Project, key)
+ }
}
parser := aggregateLimitConfigValueParsers[key]
@@ -832,6 +854,9 @@ var aggregateLimitConfigValueParsers = map[string]func(string) (int64, error){
return int64(limit), nil
},
+ "limits.disk": func(value string) (int64, error) {
+ return units.ParseByteSizeString(value)
+ },
}
var aggregateLimitConfigValuePrinters = map[string]func(int64) string{
@@ -844,4 +869,7 @@ var aggregateLimitConfigValuePrinters = map[string]func(int64) string{
"limits.cpu": func(limit int64) string {
return fmt.Sprintf("%d", limit)
},
+ "limits.disk": func(limit int64) string {
+ return units.GetByteSizeString(limit, 1)
+ },
}
From 7d9fde021bac46e27771985ad9ac3c29d7e0a6cb Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Tue, 14 Jul 2020 14:46:28 +0200
Subject: [PATCH 6/6] test: Add tests for the "limits.disk" project config key
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
test/suites/projects.sh | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/test/suites/projects.sh b/test/suites/projects.sh
index e7f9458a43..83cea1cb54 100644
--- a/test/suites/projects.sh
+++ b/test/suites/projects.sh
@@ -633,6 +633,33 @@ test_projects_limits() {
lxc profile set default limits.cpu=3
lxc config set c2 limits.cpu=3
+ # Can't set the project's disk limit because not all instances have
+ # the "size" config defined on the root device.
+ ! lxc project set p1 limits.disk 1GB || false
+
+ # Set a disk limit on the default profile and also on instance c2
+ lxc profile device set default root size=100MB
+ lxc config device add c2 root disk path="/" pool="${pool}" size=50MB
+
+ # Can't set the project's disk limit below the current aggregate count.
+ ! lxc project set p1 limits.disk 100MB || false
+
+ # Set the project's disk limit
+ lxc project set p1 limits.disk 200MB
+
+ # Can't update the project's disk limit below the current aggregate count.
+ ! lxc project set p1 limits.disk 100MB || false
+
+ # Changing profile or instance root device size above the aggregate project's
+ # limit is not possible.
+ ! lxc profile device set default root size=160MB || false
+ ! lxc config device set c2 root size 110MB || false
+
+ # Disk limits can be updated if they stay within limits.
+ lxc project set p1 limits.disk 150MB
+ lxc profile device set default root size=90MB
+ lxc config device set c2 root size 60MB
+
lxc delete c1
lxc delete c2
lxc image delete testimage
More information about the lxc-devel
mailing list