[lxc-devel] [lxd/master] [RFC] Project restrictions
freeekanayaka on Github
lxc-bot at linuxcontainers.org
Fri Feb 28 10:27:15 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 960 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200228/75a619a3/attachment-0001.bin>
-------------- next part --------------
From 1e537fae51eaaaad60e388573a396f4b74f81fca Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Fri, 28 Feb 2020 09:21:11 +0000
Subject: [PATCH 01/10] lxd/project: Rename limits.go to permissions.go
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
lxd/project/{limits.go => permissions.go} | 0
lxd/project/{limits_test.go => permissions_test.go} | 0
2 files changed, 0 insertions(+), 0 deletions(-)
rename lxd/project/{limits.go => permissions.go} (100%)
rename lxd/project/{limits_test.go => permissions_test.go} (100%)
diff --git a/lxd/project/limits.go b/lxd/project/permissions.go
similarity index 100%
rename from lxd/project/limits.go
rename to lxd/project/permissions.go
diff --git a/lxd/project/limits_test.go b/lxd/project/permissions_test.go
similarity index 100%
rename from lxd/project/limits_test.go
rename to lxd/project/permissions_test.go
From 4083752241b40f864ee91ae5c12f9b66c56e1b14 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Fri, 28 Feb 2020 09:22:48 +0000
Subject: [PATCH 02/10] lxd/project: Rename CheckLimitsUponInstanceCreation to
AllowInstanceCreation
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
lxd/containers_post.go | 4 ++--
lxd/project/permissions.go | 6 +++---
lxd/project/permissions_test.go | 16 ++++++++--------
3 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/lxd/containers_post.go b/lxd/containers_post.go
index 4836d1965a..be1ef20666 100644
--- a/lxd/containers_post.go
+++ b/lxd/containers_post.go
@@ -13,7 +13,7 @@ import (
"os"
"strings"
- "github.com/dustinkirkland/golang-petname"
+ petname "github.com/dustinkirkland/golang-petname"
"github.com/gorilla/websocket"
"github.com/pkg/errors"
@@ -825,7 +825,7 @@ func containersPost(d *Daemon, r *http.Request) response.Response {
}
}
- err := projecthelpers.CheckLimitsUponInstanceCreation(tx, project, req)
+ err := projecthelpers.AllowInstanceCreation(tx, project, req)
if err != nil {
return err
}
diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index f2df2467c6..b74b918feb 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -13,9 +13,9 @@ import (
"github.com/pkg/errors"
)
-// CheckLimitsUponInstanceCreation returns an error if any project-specific
-// limit is violated when creating a new instance.
-func CheckLimitsUponInstanceCreation(tx *db.ClusterTx, projectName string, req api.InstancesPost) error {
+// AllowInstanceCreation returns an error if any project-specific limit or
+// restriction is violated when creating a new instance.
+func AllowInstanceCreation(tx *db.ClusterTx, projectName string, req api.InstancesPost) error {
project, profiles, instances, err := fetchProject(tx, projectName, true)
if err != nil {
return err
diff --git a/lxd/project/permissions_test.go b/lxd/project/permissions_test.go
index 89f96f4bed..d81f4fee26 100644
--- a/lxd/project/permissions_test.go
+++ b/lxd/project/permissions_test.go
@@ -12,7 +12,7 @@ import (
)
// If there's no limit configured on the project, the check passes.
-func TestCheckLimitsUponInstanceCreation_NotConfigured(t *testing.T) {
+func TestAllowInstanceCreation_NotConfigured(t *testing.T) {
tx, cleanup := db.NewTestClusterTx(t)
defer cleanup()
@@ -20,12 +20,12 @@ func TestCheckLimitsUponInstanceCreation_NotConfigured(t *testing.T) {
Name: "c1",
Type: api.InstanceTypeContainer,
}
- err := project.CheckLimitsUponInstanceCreation(tx, "default", req)
+ err := project.AllowInstanceCreation(tx, "default", req)
assert.NoError(t, err)
}
// If a limit is configured and the current number of instances is below it, the check passes.
-func TestCheckLimitsUponInstanceCreation_Below(t *testing.T) {
+func TestAllowInstanceCreation_Below(t *testing.T) {
tx, cleanup := db.NewTestClusterTx(t)
defer cleanup()
@@ -53,13 +53,13 @@ func TestCheckLimitsUponInstanceCreation_Below(t *testing.T) {
Type: api.InstanceTypeContainer,
}
- err = project.CheckLimitsUponInstanceCreation(tx, "p1", req)
+ err = project.AllowInstanceCreation(tx, "p1", req)
assert.NoError(t, err)
}
// If a limit is configured and it matches the current number of instances, the
// check fails.
-func TestCheckLimitsUponInstanceCreation_Above(t *testing.T) {
+func TestAllowInstanceCreation_Above(t *testing.T) {
tx, cleanup := db.NewTestClusterTx(t)
defer cleanup()
@@ -87,13 +87,13 @@ func TestCheckLimitsUponInstanceCreation_Above(t *testing.T) {
Type: api.InstanceTypeContainer,
}
- err = project.CheckLimitsUponInstanceCreation(tx, "p1", req)
+ err = project.AllowInstanceCreation(tx, "p1", req)
assert.EqualError(t, err, "Reached maximum number of instances of type container in project p1")
}
// If a limit is configured, but for a different instance type, the check
// passes.
-func TestCheckLimitsUponInstanceCreation_DifferentType(t *testing.T) {
+func TestAllowInstanceCreation_DifferentType(t *testing.T) {
tx, cleanup := db.NewTestClusterTx(t)
defer cleanup()
@@ -121,6 +121,6 @@ func TestCheckLimitsUponInstanceCreation_DifferentType(t *testing.T) {
Type: api.InstanceTypeContainer,
}
- err = project.CheckLimitsUponInstanceCreation(tx, "p1", req)
+ err = project.AllowInstanceCreation(tx, "p1", req)
assert.NoError(t, err)
}
From 4f71e94f5873bbfd4552f82470c6743061390f0c Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Fri, 28 Feb 2020 09:23:45 +0000
Subject: [PATCH 03/10] lxd/project: Rename CheckLimitsUponInstanceUpdate to
AllowInstanceUpdate
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
lxd/container_patch.go | 2 +-
lxd/container_put.go | 2 +-
lxd/project/permissions.go | 6 +++---
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/lxd/container_patch.go b/lxd/container_patch.go
index cbc609b994..cbd36fad56 100644
--- a/lxd/container_patch.go
+++ b/lxd/container_patch.go
@@ -123,7 +123,7 @@ func containerPatch(d *Daemon, r *http.Request) response.Response {
// Check project limits.
err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
- return projecthelpers.CheckLimitsUponInstanceUpdate(tx, project, name, req)
+ return projecthelpers.AllowInstanceUpdate(tx, project, name, req)
})
if err != nil {
return response.SmartError(err)
diff --git a/lxd/container_put.go b/lxd/container_put.go
index 443d6ad503..8cd0130301 100644
--- a/lxd/container_put.go
+++ b/lxd/container_put.go
@@ -68,7 +68,7 @@ func containerPut(d *Daemon, r *http.Request) response.Response {
// Check project limits.
err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
- return projecthelpers.CheckLimitsUponInstanceUpdate(tx, project, name, configRaw)
+ return projecthelpers.AllowInstanceUpdate(tx, project, name, configRaw)
})
if err != nil {
return response.SmartError(err)
diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index b74b918feb..c1ebda6590 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -109,9 +109,9 @@ func checkAggregateInstanceLimits(tx *db.ClusterTx, project *api.Project, instan
return nil
}
-// CheckLimitsUponInstanceUpdate returns an error if any project-specific limit
-// is violated when updating an existing instance.
-func CheckLimitsUponInstanceUpdate(tx *db.ClusterTx, projectName, instanceName string, req api.InstancePut) error {
+// AllowInstanceUpdate returns an error if any project-specific limit or
+// restriction is violated when updating an existing instance.
+func AllowInstanceUpdate(tx *db.ClusterTx, projectName, instanceName string, req api.InstancePut) error {
project, profiles, instances, err := fetchProject(tx, projectName, true)
if err != nil {
return err
From 60de388f9af6fce5764e2078dee98a189bcec927 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Fri, 28 Feb 2020 09:24:53 +0000
Subject: [PATCH 04/10] lxd/project: Rename CheckLimitsUponProfileUpdate to
AllowProfileUpdate
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
lxd/profiles_utils.go | 2 +-
lxd/project/permissions.go | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/lxd/profiles_utils.go b/lxd/profiles_utils.go
index e506d56e64..cdbfc2d623 100644
--- a/lxd/profiles_utils.go
+++ b/lxd/profiles_utils.go
@@ -18,7 +18,7 @@ import (
func doProfileUpdate(d *Daemon, project, name string, id int64, profile *api.Profile, req api.ProfilePut) error {
// Check project limits.
err := d.cluster.Transaction(func(tx *db.ClusterTx) error {
- return projecthelpers.CheckLimitsUponProfileUpdate(tx, project, name, req)
+ return projecthelpers.AllowProfileUpdate(tx, project, name, req)
})
if err != nil {
return err
diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index c1ebda6590..11845c1be2 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -137,9 +137,9 @@ func AllowInstanceUpdate(tx *db.ClusterTx, projectName, instanceName string, req
return nil
}
-// CheckLimitsUponProfileUpdate checks that project limits are not violated
-// when changing a profile.
-func CheckLimitsUponProfileUpdate(tx *db.ClusterTx, projectName, profileName string, req api.ProfilePut) error {
+// AllowProfileUpdate checks that project limits and restrictions are not
+// violated when changing a profile.
+func AllowProfileUpdate(tx *db.ClusterTx, projectName, profileName string, req api.ProfilePut) error {
project, profiles, instances, err := fetchProject(tx, projectName, true)
if err != nil {
return err
From 029593a83abc9b1192fdffbf285a2b29a094f3df Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Fri, 28 Feb 2020 09:25:56 +0000
Subject: [PATCH 05/10] lxd/project: Rename ValidateLimitsUponProjectUpdate to
AllowProjectUpdate
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
lxd/api_project.go | 2 +-
lxd/project/permissions.go | 5 ++---
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/lxd/api_project.go b/lxd/api_project.go
index 32c0ce17b7..da215c2004 100644
--- a/lxd/api_project.go
+++ b/lxd/api_project.go
@@ -358,7 +358,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.ValidateLimitsUponProjectUpdate(tx, project.Name, req.Config, configChanged)
+ err := projecthelpers.AllowProjectUpdate(tx, project.Name, req.Config, configChanged)
if err != nil {
return err
}
diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index 11845c1be2..c1a6a722fd 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -164,9 +164,8 @@ func AllowProfileUpdate(tx *db.ClusterTx, projectName, profileName string, req a
return nil
}
-// ValidateLimitsUponProjectUpdate checks the new limits to be set on a project
-// are valid.
-func ValidateLimitsUponProjectUpdate(tx *db.ClusterTx, projectName string, config map[string]string, changed []string) error {
+// AllowProjectUpdate checks the new config to be set on a project is valid.
+func AllowProjectUpdate(tx *db.ClusterTx, projectName string, config map[string]string, changed []string) error {
_, profiles, instances, err := fetchProject(tx, projectName, false)
if err != nil {
return err
From dc6bd336f0665388cf983933cdf205a682561296 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Fri, 28 Feb 2020 09:28:24 +0000
Subject: [PATCH 06/10] lxd/project: Rename checkAggregateInstanceLimits to
checkRestrictionsAndAggregateLimits
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
lxd/project/permissions.go | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index c1a6a722fd..7c9b4eded7 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -35,7 +35,7 @@ func AllowInstanceCreation(tx *db.ClusterTx, projectName string, req api.Instanc
Config: req.Config,
})
- err = checkAggregateInstanceLimits(tx, project, instances, profiles)
+ err = checkRestrictionsAndAggregateLimits(tx, project, instances, profiles)
if err != nil {
return err
}
@@ -71,9 +71,9 @@ func checkInstanceCountLimit(project *api.Project, instanceCount int, instanceTy
return nil
}
-// Check that we would not violate the project limits if we were to commit the
-// given instances and profiles.
-func checkAggregateInstanceLimits(tx *db.ClusterTx, project *api.Project, instances []db.Instance, profiles []db.Profile) error {
+// Check that we would not violate the project limits or restrictions if we
+// were to commit the given instances and profiles.
+func checkRestrictionsAndAggregateLimits(tx *db.ClusterTx, project *api.Project, instances []db.Instance, profiles []db.Profile) error {
// List of config keys for which we need to check aggregate values
// across all project instances.
aggregateKeys := []string{}
@@ -129,7 +129,7 @@ func AllowInstanceUpdate(tx *db.ClusterTx, projectName, instanceName string, req
instances[i].Config = req.Config
}
- err = checkAggregateInstanceLimits(tx, project, instances, profiles)
+ err = checkRestrictionsAndAggregateLimits(tx, project, instances, profiles)
if err != nil {
return err
}
@@ -156,7 +156,7 @@ func AllowProfileUpdate(tx *db.ClusterTx, projectName, profileName string, req a
profiles[i].Config = req.Config
}
- err = checkAggregateInstanceLimits(tx, project, instances, profiles)
+ err = checkRestrictionsAndAggregateLimits(tx, project, instances, profiles)
if err != nil {
return err
}
From 89ef6ab892ab66e333f1e11a5ad514179826ca0c Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Fri, 28 Feb 2020 09:35:06 +0000
Subject: [PATCH 07/10] lxd/project: Extract checkAggregateLimits from
checkRestrictionsAndAggregateLimits
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
lxd/project/permissions.go | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index 7c9b4eded7..d5af664078 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -78,16 +78,26 @@ func checkRestrictionsAndAggregateLimits(tx *db.ClusterTx, project *api.Project,
// across all project instances.
aggregateKeys := []string{}
for key := range project.Config {
- if shared.StringInSlice(key, []string{"limits.memory", "limits.processes", "limits.cpu"}) {
+ if shared.StringInSlice(key, allAggregateLimits) {
aggregateKeys = append(aggregateKeys, key)
}
}
+
if len(aggregateKeys) == 0 {
return nil
}
instances = expandInstancesConfig(instances, profiles)
+ err := checkAggregateLimits(project, instances, aggregateKeys)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func checkAggregateLimits(project *api.Project, instances []db.Instance, aggregateKeys []string) error {
totals, err := getTotalsAcrossInstances(instances, aggregateKeys)
if err != nil {
return err
@@ -105,10 +115,15 @@ func checkRestrictionsAndAggregateLimits(tx *db.ClusterTx, project *api.Project,
project.Config[key], key, project.Name)
}
}
-
return nil
}
+var allAggregateLimits = []string{
+ "limits.cpu",
+ "limits.memory",
+ "limits.processes",
+}
+
// AllowInstanceUpdate returns an error if any project-specific limit or
// restriction is violated when updating an existing instance.
func AllowInstanceUpdate(tx *db.ClusterTx, projectName, instanceName string, req api.InstancePut) error {
From 1d6d91251bcf9b3b9912d34e39b609ebf9ed9064 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Fri, 28 Feb 2020 09:56:46 +0000
Subject: [PATCH 08/10] lxd/project: Honor the "restrict.containers.nesting"
config
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
lxd/project/permissions.go | 72 +++++++++++++++++++++++++++++++++++---
1 file changed, 67 insertions(+), 5 deletions(-)
diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index d5af664078..bfcdad0059 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -31,6 +31,7 @@ func AllowInstanceCreation(tx *db.ClusterTx, projectName string, req api.Instanc
// Add the instance being created.
instances = append(instances, db.Instance{
+ Name: req.Name,
Profiles: req.Profiles,
Config: req.Config,
})
@@ -83,7 +84,15 @@ func checkRestrictionsAndAggregateLimits(tx *db.ClusterTx, project *api.Project,
}
}
- if len(aggregateKeys) == 0 {
+ // List of restriction-related keys.
+ restrictionKeys := []string{}
+ for key := range project.Config {
+ if shared.StringInSlice(key, allRestrictions) {
+ restrictionKeys = append(restrictionKeys, key)
+ }
+ }
+
+ if len(aggregateKeys) == 0 && len(restrictionKeys) == 0 {
return nil
}
@@ -94,10 +103,19 @@ func checkRestrictionsAndAggregateLimits(tx *db.ClusterTx, project *api.Project,
return err
}
+ err = checkRestrictions(project, instances, restrictionKeys)
+ if err != nil {
+ return err
+ }
+
return nil
}
func checkAggregateLimits(project *api.Project, instances []db.Instance, aggregateKeys []string) error {
+ if len(aggregateKeys) == 0 {
+ return nil
+ }
+
totals, err := getTotalsAcrossInstances(instances, aggregateKeys)
if err != nil {
return err
@@ -118,12 +136,56 @@ func checkAggregateLimits(project *api.Project, instances []db.Instance, aggrega
return nil
}
+func checkRestrictions(project *api.Project, instances []db.Instance, restrictionKeys []string) error {
+ if len(restrictionKeys) == 0 {
+ return nil
+ }
+
+ containerKeyChecks := map[string]func(value string) error{}
+
+ for _, key := range restrictionKeys {
+ switch key {
+ case "restrict.containers.nesting":
+ containerKeyChecks["security.nesting"] = func(value string) error {
+ if !shared.IsTrue(value) {
+ return nil
+ }
+ return fmt.Errorf("Container nesting is forbidden")
+ }
+ }
+ }
+
+ for _, instance := range instances {
+ if instance.Type == instancetype.Container {
+ for key, value := range instance.Config {
+ checker, ok := containerKeyChecks[key]
+ if !ok {
+ continue
+ }
+ err := checker(value)
+ if err != nil {
+ return errors.Wrapf(
+ err,
+ "Invalid value %q for config %q on instance %q of project %q",
+ value, key, instance.Name, project.Name)
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
var allAggregateLimits = []string{
"limits.cpu",
"limits.memory",
"limits.processes",
}
+var allRestrictions = []string{
+ "restrict.containers.nesting",
+}
+
// AllowInstanceUpdate returns an error if any project-specific limit or
// restriction is violated when updating an existing instance.
func AllowInstanceUpdate(tx *db.ClusterTx, projectName, instanceName string, req api.InstancePut) error {
@@ -277,10 +339,10 @@ func validateAggregateLimit(totals map[string]int64, key, value string) error {
return nil
}
-// Return true if the project has some limits.
-func projectHasLimits(project *api.Project) bool {
+// Return true if the project has some limits or restrictions set.
+func projectHasLimitsOrRestrictions(project *api.Project) bool {
for k := range project.Config {
- if strings.HasPrefix(k, "limits.") {
+ if strings.HasPrefix(k, "limits.") || strings.HasPrefix(k, "restrict.") {
return true
}
}
@@ -297,7 +359,7 @@ func fetchProject(tx *db.ClusterTx, projectName string, skipIfNoLimits bool) (*a
return nil, nil, nil, errors.Wrap(err, "Fetch project database object")
}
- if skipIfNoLimits && !projectHasLimits(project) {
+ if skipIfNoLimits && !projectHasLimitsOrRestrictions(project) {
return nil, nil, nil, nil
}
From e6d2f4b8c7c4e9374a428e38491c0ceb117e0c92 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Fri, 28 Feb 2020 09:10:59 +0000
Subject: [PATCH 09/10] api: Add new restrict.* config keys to projects
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
lxd/api_project.go | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/lxd/api_project.go b/lxd/api_project.go
index da215c2004..e736671a45 100644
--- a/lxd/api_project.go
+++ b/lxd/api_project.go
@@ -515,13 +515,14 @@ func projectIsEmpty(project *api.Project) bool {
// Validate the project configuration
var projectConfigKeys = map[string]func(value string) error{
- "features.profiles": shared.IsBool,
- "features.images": shared.IsBool,
- "limits.containers": shared.IsUint32,
- "limits.virtual-machines": shared.IsUint32,
- "limits.memory": shared.IsSize,
- "limits.processes": shared.IsUint32,
- "limits.cpu": shared.IsUint32,
+ "features.profiles": shared.IsBool,
+ "features.images": shared.IsBool,
+ "limits.containers": shared.IsUint32,
+ "limits.virtual-machines": shared.IsUint32,
+ "limits.memory": shared.IsSize,
+ "limits.processes": shared.IsUint32,
+ "limits.cpu": shared.IsUint32,
+ "restrict.containers.nesting": shared.IsBool,
}
func projectValidateConfig(config map[string]string) error {
From 522f9dda3f8adf0f678db866bcec5b1b1d92390b Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Fri, 28 Feb 2020 10:18:04 +0000
Subject: [PATCH 10/10] test: Add projects restrictions tests
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
test/main.sh | 1 +
test/suites/projects.sh | 25 +++++++++++++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/test/main.sh b/test/main.sh
index 8c142cdb39..7a56b501b8 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -193,6 +193,7 @@ run_test test_projects_images_default "images from the global default project"
run_test test_projects_storage "projects and storage pools"
run_test test_projects_network "projects and networks"
run_test test_projects_limits "projects limits"
+run_test test_projects_restrictions "projects restrictions"
run_test test_container_devices_disk "container devices - disk"
run_test test_container_devices_nic_p2p "container devices - nic - p2p"
run_test test_container_devices_nic_bridged "container devices - nic - bridged"
diff --git a/test/suites/projects.sh b/test/suites/projects.sh
index c8060f2d9a..9980f7bee8 100644
--- a/test/suites/projects.sh
+++ b/test/suites/projects.sh
@@ -625,3 +625,28 @@ test_projects_limits() {
lxc project switch default
lxc project delete p1
}
+
+# Set restrictions on projects.
+test_projects_restrictions() {
+ # Create a project
+ lxc project create p1
+
+ lxc project switch p1
+
+ # Add a root device to the default profile of the project and import an image.
+ pool="lxdtest-$(basename "${LXD_DIR}")"
+ lxc profile device add default root disk path="/" pool="${pool}"
+
+ deps/import-busybox --project p1 --alias testimage
+ fingerprint="$(lxc image list -c f --format json | jq -r .[0].fingerprint)"
+
+ # Create a couple of containers in the project.
+ lxc project set p1 restrict.containers.nesting=true
+
+ ! lxc init testimage c1 -c security.nesting=true || false
+
+ lxc image delete testimage
+
+ lxc project switch default
+ lxc project delete p1
+}
More information about the lxc-devel
mailing list