[lxc-devel] [lxd/master] Adds a new 'limits.instances' key in project
kevtheappdev on Github
lxc-bot at linuxcontainers.org
Mon Dec 7 06:02:54 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 314 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20201206/bfa78558/attachment.bin>
-------------- next part --------------
From 17a021048c153783a97748f09db5ca62141d7361 Mon Sep 17 00:00:00 2001
From: Max Patrick <maxpat21 at verizon.net>
Date: Mon, 7 Dec 2020 11:24:36 +0530
Subject: [PATCH 1/3] doc: Adds limits.instances key description.
Signed-off-by: Kevin Turner <kevinturner at utexas.edu>
---
doc/projects.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc/projects.md b/doc/projects.md
index 462864fabb..65a54f9266 100644
--- a/doc/projects.md
+++ b/doc/projects.md
@@ -21,6 +21,7 @@ features.images | boolean | - | true
features.networks | boolean | - | true | Separate set of networks for the project
features.profiles | boolean | - | true | Separate set of profiles for the project
features.storage.volumes | boolean | - | true | Separate set of storage volumes for the project
+limits.instances | integer | - | - | Maximum number of total instances that can be created in the project
limits.containers | integer | - | - | Maximum number of containers 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.disk | string | - | - | Maximum value of aggregate disk space used by all instances volumes, custom volumes and images of the project
From 2d5fc48461dac7d3bfceecade9c1765f361f606b Mon Sep 17 00:00:00 2001
From: Max Patrick <maxpat21 at verizon.net>
Date: Mon, 7 Dec 2020 11:25:23 +0530
Subject: [PATCH 2/3] api: Adds limits.instances
Signed-off-by: Kevin Turner <kevinturner at utexas.edu>
---
lxd/api_project.go | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lxd/api_project.go b/lxd/api_project.go
index 5c4993cec1..c87cf8e20e 100644
--- a/lxd/api_project.go
+++ b/lxd/api_project.go
@@ -351,6 +351,7 @@ func projectChange(d *Daemon, project *api.Project, req api.ProjectPut) response
// Update the database entry.
err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
err := projecthelpers.AllowProjectUpdate(tx, project.Name, req.Config, configChanged)
+
if err != nil {
return err
}
@@ -524,6 +525,7 @@ func projectValidateConfig(s *state.State, config map[string]string) error {
"features.images": validate.Optional(validate.IsBool),
"features.storage.volumes": validate.Optional(validate.IsBool),
"features.networks": validate.Optional(validate.IsBool),
+ "limits.instances": validate.Optional(validate.IsUint32),
"limits.containers": validate.Optional(validate.IsUint32),
"limits.virtual-machines": validate.Optional(validate.IsUint32),
"limits.memory": validate.Optional(validate.IsSize),
From bbbd95b3d82c86ac63897de856cf4b12676e5d09 Mon Sep 17 00:00:00 2001
From: Max Patrick <maxpat21 at verizon.net>
Date: Mon, 7 Dec 2020 11:26:03 +0530
Subject: [PATCH 3/3] lxd/project: Adds 'limits.instances' configuration key
Signed-Off-By: Kevin Turner <kevinturner at utexas.edu>
---
lxd/api_project.go | 2 +-
lxd/project/permissions.go | 52 +++++++++++++++++++++++++++++++++
lxd/project/permissions_test.go | 35 ++++++++++++++++++++++
3 files changed, 88 insertions(+), 1 deletion(-)
diff --git a/lxd/api_project.go b/lxd/api_project.go
index c87cf8e20e..103faafd32 100644
--- a/lxd/api_project.go
+++ b/lxd/api_project.go
@@ -525,7 +525,7 @@ func projectValidateConfig(s *state.State, config map[string]string) error {
"features.images": validate.Optional(validate.IsBool),
"features.storage.volumes": validate.Optional(validate.IsBool),
"features.networks": validate.Optional(validate.IsBool),
- "limits.instances": validate.Optional(validate.IsUint32),
+ "limits.instances": validate.Optional(validate.IsUint32),
"limits.containers": validate.Optional(validate.IsUint32),
"limits.virtual-machines": validate.Optional(validate.IsUint32),
"limits.memory": validate.Optional(validate.IsSize),
diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index 74e9f0380f..df12ef97be 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -56,6 +56,12 @@ func AllowInstanceCreation(tx *db.ClusterTx, projectName string, req api.Instanc
return err
}
+ totalInstanceCount := len(info.Instances)
+ err = checkTotalInstanceCountLimit(info.Project, totalInstanceCount)
+ if err != nil {
+ return err
+ }
+
// Add the instance being created.
info.Instances = append(info.Instances, db.Instance{
Name: req.Name,
@@ -79,6 +85,27 @@ func AllowInstanceCreation(tx *db.ClusterTx, projectName string, req api.Instanc
return nil
}
+// Check that we have not exceeded the maximum total alotted number of instances
+// for both containers and vms
+
+func checkTotalInstanceCountLimit(project *api.Project, totalInstanceCount int) error {
+
+ overallValue, ok := project.Config["limits.instances"]
+ if ok {
+ limit, err := strconv.Atoi(overallValue)
+ if err != nil || limit < 0 {
+ return fmt.Errorf("Unexpected limits.instances value: %q", overallValue)
+ }
+
+ if totalInstanceCount >= limit {
+ return fmt.Errorf(
+ "Reached maximum number of instances in project %q",
+ project.Name)
+ }
+ }
+ return nil
+}
+
// Check that we have not reached the maximum number of instances for
// this type.
func checkInstanceCountLimit(project *api.Project, instanceCount int, instanceType instancetype.Type) error {
@@ -716,6 +743,11 @@ func AllowProjectUpdate(tx *db.ClusterTx, projectName string, config map[string]
}
switch key {
+ case "limits.instances":
+ err := validateTotalInstanceCountLimit(info.Instances, config[key], projectName)
+ if err != nil {
+ return errors.Wrapf(err, "Can't change limits.instances in project %q", projectName)
+ }
case "limits.containers":
fallthrough
case "limits.virtual-machines":
@@ -752,6 +784,26 @@ func AllowProjectUpdate(tx *db.ClusterTx, projectName string, config map[string]
return nil
}
+// Check that limits.instances, i.e. the total limit of containers/virtual machines allocated
+// to the user is equal to or above the current count
+func validateTotalInstanceCountLimit(instances []db.Instance, value, project string) error {
+ if value == "" {
+ return nil
+ }
+
+ limit, err := strconv.Atoi(value)
+ if err != nil {
+ return err
+ }
+
+ count := len(instances)
+
+ if limit < count {
+ return fmt.Errorf("'limits.instances' is too low: there currently are %d total instances in project %s", count, project)
+ }
+ return nil
+}
+
// Check that limits.containers or limits.virtual-machines is equal or above
// the current count.
func validateInstanceCountLimit(instances []db.Instance, key, value, project string) error {
diff --git a/lxd/project/permissions_test.go b/lxd/project/permissions_test.go
index ccede05630..41e5daebe3 100644
--- a/lxd/project/permissions_test.go
+++ b/lxd/project/permissions_test.go
@@ -124,3 +124,38 @@ func TestAllowInstanceCreation_DifferentType(t *testing.T) {
err = project.AllowInstanceCreation(tx, "p1", req)
assert.NoError(t, err)
}
+
+// If a limit is configured, but the limit on instances is more
+// restrictive, the check fails
+func TestAllowInstanceCreation_AboveInstances(t *testing.T) {
+ tx, cleanup := db.NewTestClusterTx(t)
+ defer cleanup()
+
+ _, err := tx.CreateProject(api.ProjectsPost{
+ Name: "p1",
+ ProjectPut: api.ProjectPut{
+ Config: map[string]string{
+ "limits.containers": "5",
+ "limits.instances" : "1",
+ },
+ },
+ })
+ require.NoError(t, err)
+
+ _, err = tx.CreateInstance(db.Instance{
+ Project: "p1",
+ Name: "c1",
+ Type: instancetype.Container,
+ Architecture: 1,
+ Node: "none",
+ })
+ require.NoError(t, err)
+
+ req := api.InstancesPost{
+ Name: "c2",
+ Type: api.InstanceTypeContainer,
+ }
+
+ err = project.AllowInstanceCreation(tx, "p1", req)
+ assert.EqualError(t, err, `Reached maximum number of instances in project "p1"`)
+}
\ No newline at end of file
More information about the lxc-devel
mailing list