The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6952
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) === This is just a preview in order to get some feedback. @stgraber essentially the approach that I'd take is that each of the ```restrict.*``` project configuration key has an impact on the allowed values of one or more instance-level config key. For example if you set ```restrict.containers.nesting```, then ```security.nesting``` can't be ```true``` in any container in the project. I'm not totally sure if: 1. This approach will be fine for all other ```resctrict.*``` keys. 2. Which instance-level config keys and values will map to which ```restrict.X``` key(s) However, assuming that 1. is ok, we can figure out 2. little by little as we go.
From 1e537fae51eaaaad60e388573a396f4b74f81fca Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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.ekanay...@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 +}
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel