The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/8217

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) ===
Fixes #7925. 
From 17a021048c153783a97748f09db5ca62141d7361 Mon Sep 17 00:00:00 2001
From: Max Patrick <maxpa...@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 <kevintur...@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 <maxpa...@verizon.net>
Date: Mon, 7 Dec 2020 11:25:23 +0530
Subject: [PATCH 2/3] api: Adds limits.instances

Signed-off-by: Kevin Turner <kevintur...@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 <maxpa...@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 <kevintur...@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
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to