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

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) ===
Initial abstraction to support different properties and controllers for https://github.com/lxc/lxd/issues/6305.
From 8b76c03441f915acf68e8e16434e457ae82d41b3 Mon Sep 17 00:00:00 2001
From: Shreyas Sood <shreyass...@gmail.com>
Date: Sun, 8 Dec 2019 19:49:39 -0600
Subject: [PATCH] lxd/cgroup: Initial abstraction for cgroupsv2 with pids
 support

---
 lxd/cgroup/cgroup.go               |  69 ++++++++++++++++++
 lxd/container_lxc.go               | 108 ++++++++++++++++++++---------
 lxd/devices.go                     |   4 +-
 lxd/instance/instance_interface.go |   7 +-
 lxd/instance/qemu/vm_qemu.go       |  17 ++++-
 5 files changed, 165 insertions(+), 40 deletions(-)
 create mode 100644 lxd/cgroup/cgroup.go

diff --git a/lxd/cgroup/cgroup.go b/lxd/cgroup/cgroup.go
new file mode 100644
index 0000000000..cc3ecba6f4
--- /dev/null
+++ b/lxd/cgroup/cgroup.go
@@ -0,0 +1,69 @@
+package cgroup
+
+import (
+       "fmt"
+       "gopkg.in/lxc/go-lxc.v2"
+)
+
+type Property int
+const (
+       PidsCurrent Property = iota
+       PidsMax
+)
+
+type configItem struct {
+       Key string
+       Value string
+}
+
+// Get finds property values on a lxcContainer
+func Get(c *lxc.Container, property Property) ([]string, error) {
+       switch property {
+
+       // Properties which have the same functionality for both v1 and v2
+       case PidsCurrent:
+               return c.CgroupItem("pids.current"), nil
+       }
+
+       return nil, fmt.Errorf("CGroup Property not supported for Get")
+}
+
+// Set sets a property on a lxcContainer
+func Set(c *lxc.Container, property Property, value string) error {
+
+       configs, e := SetConfigMap(property, value)
+       if e != nil {
+               return e
+       }
+
+       for _, rule :=  range configs {
+               err := c.SetCgroupItem(rule.Key, rule.Value)
+
+               if err != nil {
+                       return fmt.Errorf("Failure while trying to set 
property: %s", err)
+               }
+       }
+
+       return nil
+}
+
+// SetConfigMap returns different cgroup configs to set a particular property
+func SetConfigMap(property Property, value string) ([]configItem, error) {
+
+       switch property {
+
+       // Properties which have the same functionality for both v1 and v2
+       case PidsCurrent:
+               return []configItem{
+                       {Key: "pids.current", Value: value},
+               }, nil
+
+       case PidsMax:
+               return []configItem{
+                       {Key: "pids.max", Value: value},
+               }, nil
+
+       }
+
+       return nil, fmt.Errorf("CGroup Property not supported for Set")
+}
\ No newline at end of file
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 4c6bb2999d..c9a39492c5 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -1405,7 +1405,7 @@ func (c *containerLXC) deviceAddCgroupRules(cgroups 
[]deviceConfig.RunConfigItem
                }
 
                // Add the new device cgroup rule.
-               err := c.CGroupSet(rule.Key, rule.Value)
+               err := c.CGroupSetV1(rule.Key, rule.Value)
                if err != nil {
                        return fmt.Errorf("Failed to add cgroup rule for 
device")
                }
@@ -2592,7 +2592,7 @@ func (c *containerLXC) Stop(stateful bool) error {
        // Fork-bomb mitigation, prevent forking from this point on
        if c.state.OS.CGroupPidsController {
                // Attempt to disable forking new processes
-               c.CGroupSet("pids.max", "0")
+               c.CGroupSet(cgroup.PidsMax, "0")
        } else if c.state.OS.CGroupFreezerController {
                // Attempt to freeze the container
                freezer := make(chan bool, 1)
@@ -3769,7 +3769,28 @@ func (c *containerLXC) Rename(newName string) error {
        return nil
 }
 
-func (c *containerLXC) CGroupGet(key string) (string, error) {
+// CGroupGet gets the value of a supported property on a hybrid v1/v2 
controller system
+func (c *containerLXC) CGroupGet(property cgroup.Property) (string, error) {
+       // Load the go-lxc struct
+       err := c.initLXC(false)
+       if err != nil {
+               return "", err
+       }
+
+       // Make sure the container is running
+       if !c.IsRunning() {
+               return "", fmt.Errorf("Can't get cgroups on a stopped 
container")
+       }
+
+       value, err := cgroup.Get(c.c, property)
+
+       if err != nil {
+               return "", err
+       }
+       return strings.Join(value, "\n"), nil
+}
+
+func (c *containerLXC) CGroupGetV1(key string) (string, error) {
        // Load the go-lxc struct
        err := c.initLXC(false)
        if err != nil {
@@ -3785,7 +3806,28 @@ func (c *containerLXC) CGroupGet(key string) (string, 
error) {
        return strings.Join(value, "\n"), nil
 }
 
-func (c *containerLXC) CGroupSet(key string, value string) error {
+// CGroupSet sets a supported property on a hybrid v1/v2 controller system
+func (c *containerLXC) CGroupSet(property cgroup.Property, value string) error 
{
+       // Load the go-lxc struct
+       err := c.initLXC(false)
+       if err != nil {
+               return err
+       }
+
+       // Make sure the container is running
+       if !c.IsRunning() {
+               return fmt.Errorf("Can't set cgroups on a stopped container")
+       }
+
+       err = cgroup.Set(c.c, property, value)
+       if err != nil {
+               return fmt.Errorf("Failed to set cgroup item %d=\"%s\": %s", 
property, value, err)
+       }
+
+       return nil
+}
+
+func (c *containerLXC) CGroupSetV1(key string, value string) error {
        // Load the go-lxc struct
        err := c.initLXC(false)
        if err != nil {
@@ -4208,7 +4250,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, 
userRequested bool) error {
                                        priority = 10
                                }
 
-                               err = c.CGroupSet("blkio.weight", 
fmt.Sprintf("%d", priority))
+                               err = c.CGroupSetV1("blkio.weight", 
fmt.Sprintf("%d", priority))
                                if err != nil {
                                        return err
                                }
@@ -4249,52 +4291,52 @@ func (c *containerLXC) Update(args db.InstanceArgs, 
userRequested bool) error {
                                // Store the old values for revert
                                oldMemswLimit := ""
                                if c.state.OS.CGroupSwapAccounting {
-                                       oldMemswLimit, err = 
c.CGroupGet("memory.memsw.limit_in_bytes")
+                                       oldMemswLimit, err = 
c.CGroupGetV1("memory.memsw.limit_in_bytes")
                                        if err != nil {
                                                oldMemswLimit = ""
                                        }
                                }
 
-                               oldLimit, err := 
c.CGroupGet("memory.limit_in_bytes")
+                               oldLimit, err := 
c.CGroupGetV1("memory.limit_in_bytes")
                                if err != nil {
                                        oldLimit = ""
                                }
 
-                               oldSoftLimit, err := 
c.CGroupGet("memory.soft_limit_in_bytes")
+                               oldSoftLimit, err := 
c.CGroupGetV1("memory.soft_limit_in_bytes")
                                if err != nil {
                                        oldSoftLimit = ""
                                }
 
                                revertMemory := func() {
                                        if oldSoftLimit != "" {
-                                               
c.CGroupSet("memory.soft_limit_in_bytes", oldSoftLimit)
+                                               
c.CGroupSetV1("memory.soft_limit_in_bytes", oldSoftLimit)
                                        }
 
                                        if oldLimit != "" {
-                                               
c.CGroupSet("memory.limit_in_bytes", oldLimit)
+                                               
c.CGroupSetV1("memory.limit_in_bytes", oldLimit)
                                        }
 
                                        if oldMemswLimit != "" {
-                                               
c.CGroupSet("memory.memsw.limit_in_bytes", oldMemswLimit)
+                                               
c.CGroupSetV1("memory.memsw.limit_in_bytes", oldMemswLimit)
                                        }
                                }
 
                                // Reset everything
                                if c.state.OS.CGroupSwapAccounting {
-                                       err = 
c.CGroupSet("memory.memsw.limit_in_bytes", "-1")
+                                       err = 
c.CGroupSetV1("memory.memsw.limit_in_bytes", "-1")
                                        if err != nil {
                                                revertMemory()
                                                return err
                                        }
                                }
 
-                               err = c.CGroupSet("memory.limit_in_bytes", "-1")
+                               err = c.CGroupSetV1("memory.limit_in_bytes", 
"-1")
                                if err != nil {
                                        revertMemory()
                                        return err
                                }
 
-                               err = c.CGroupSet("memory.soft_limit_in_bytes", 
"-1")
+                               err = 
c.CGroupSetV1("memory.soft_limit_in_bytes", "-1")
                                if err != nil {
                                        revertMemory()
                                        return err
@@ -4303,26 +4345,26 @@ func (c *containerLXC) Update(args db.InstanceArgs, 
userRequested bool) error {
                                // Set the new values
                                if memoryEnforce == "soft" {
                                        // Set new limit
-                                       err = 
c.CGroupSet("memory.soft_limit_in_bytes", memory)
+                                       err = 
c.CGroupSetV1("memory.soft_limit_in_bytes", memory)
                                        if err != nil {
                                                revertMemory()
                                                return err
                                        }
                                } else {
                                        if c.state.OS.CGroupSwapAccounting && 
(memorySwap == "" || shared.IsTrue(memorySwap)) {
-                                               err = 
c.CGroupSet("memory.limit_in_bytes", memory)
+                                               err = 
c.CGroupSetV1("memory.limit_in_bytes", memory)
                                                if err != nil {
                                                        revertMemory()
                                                        return err
                                                }
 
-                                               err = 
c.CGroupSet("memory.memsw.limit_in_bytes", memory)
+                                               err = 
c.CGroupSetV1("memory.memsw.limit_in_bytes", memory)
                                                if err != nil {
                                                        revertMemory()
                                                        return err
                                                }
                                        } else {
-                                               err = 
c.CGroupSet("memory.limit_in_bytes", memory)
+                                               err = 
c.CGroupSetV1("memory.limit_in_bytes", memory)
                                                if err != nil {
                                                        revertMemory()
                                                        return err
@@ -4336,7 +4378,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, 
userRequested bool) error {
                                                return err
                                        }
 
-                                       err = 
c.CGroupSet("memory.soft_limit_in_bytes", fmt.Sprintf("%.0f", 
float64(valueInt)*0.9))
+                                       err = 
c.CGroupSetV1("memory.soft_limit_in_bytes", fmt.Sprintf("%.0f", 
float64(valueInt)*0.9))
                                        if err != nil {
                                                revertMemory()
                                                return err
@@ -4348,7 +4390,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, 
userRequested bool) error {
                                        memorySwap := 
c.expandedConfig["limits.memory.swap"]
                                        memorySwapPriority := 
c.expandedConfig["limits.memory.swap.priority"]
                                        if memorySwap != "" && 
!shared.IsTrue(memorySwap) {
-                                               err = 
c.CGroupSet("memory.swappiness", "0")
+                                               err = 
c.CGroupSetV1("memory.swappiness", "0")
                                                if err != nil {
                                                        return err
                                                }
@@ -4361,7 +4403,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, 
userRequested bool) error {
                                                        }
                                                }
 
-                                               err = 
c.CGroupSet("memory.swappiness", fmt.Sprintf("%d", 60-10+priority))
+                                               err = 
c.CGroupSetV1("memory.swappiness", fmt.Sprintf("%d", 60-10+priority))
                                                if err != nil {
                                                        return err
                                                }
@@ -4387,17 +4429,17 @@ func (c *containerLXC) Update(args db.InstanceArgs, 
userRequested bool) error {
                                        return err
                                }
 
-                               err = c.CGroupSet("cpu.shares", cpuShares)
+                               err = c.CGroupSetV1("cpu.shares", cpuShares)
                                if err != nil {
                                        return err
                                }
 
-                               err = c.CGroupSet("cpu.cfs_period_us", 
cpuCfsPeriod)
+                               err = c.CGroupSetV1("cpu.cfs_period_us", 
cpuCfsPeriod)
                                if err != nil {
                                        return err
                                }
 
-                               err = c.CGroupSet("cpu.cfs_quota_us", 
cpuCfsQuota)
+                               err = c.CGroupSetV1("cpu.cfs_quota_us", 
cpuCfsQuota)
                                if err != nil {
                                        return err
                                }
@@ -4407,7 +4449,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, 
userRequested bool) error {
                                }
 
                                if value == "" {
-                                       err = c.CGroupSet("pids.max", "max")
+                                       err = c.CGroupSet(cgroup.PidsCurrent, 
"max")
                                        if err != nil {
                                                return err
                                        }
@@ -4417,7 +4459,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, 
userRequested bool) error {
                                                return err
                                        }
 
-                                       err = c.CGroupSet("pids.max", 
fmt.Sprintf("%d", valueInt))
+                                       err = c.CGroupSet(cgroup.PidsMax, 
fmt.Sprintf("%d", valueInt))
                                        if err != nil {
                                                return err
                                        }
@@ -5732,7 +5774,7 @@ func (c *containerLXC) cpuState() api.InstanceStateCPU {
        }
 
        // CPU usage in seconds
-       value, err := c.CGroupGet("cpuacct.usage")
+       value, err := c.CGroupGetV1("cpuacct.usage")
        if err != nil {
                cpu.Usage = -1
                return cpu
@@ -5803,14 +5845,14 @@ func (c *containerLXC) memoryState() 
api.InstanceStateMemory {
        }
 
        // Memory in bytes
-       value, err := c.CGroupGet("memory.usage_in_bytes")
+       value, err := c.CGroupGetV1("memory.usage_in_bytes")
        valueInt, err1 := strconv.ParseInt(value, 10, 64)
        if err == nil && err1 == nil {
                memory.Usage = valueInt
        }
 
        // Memory peak in bytes
-       value, err = c.CGroupGet("memory.max_usage_in_bytes")
+       value, err = c.CGroupGetV1("memory.max_usage_in_bytes")
        valueInt, err1 = strconv.ParseInt(value, 10, 64)
        if err == nil && err1 == nil {
                memory.UsagePeak = valueInt
@@ -5819,7 +5861,7 @@ func (c *containerLXC) memoryState() 
api.InstanceStateMemory {
        if c.state.OS.CGroupSwapAccounting {
                // Swap in bytes
                if memory.Usage > 0 {
-                       value, err := c.CGroupGet("memory.memsw.usage_in_bytes")
+                       value, err := 
c.CGroupGetV1("memory.memsw.usage_in_bytes")
                        valueInt, err1 := strconv.ParseInt(value, 10, 64)
                        if err == nil && err1 == nil {
                                memory.SwapUsage = valueInt - memory.Usage
@@ -5828,7 +5870,7 @@ func (c *containerLXC) memoryState() 
api.InstanceStateMemory {
 
                // Swap peak in bytes
                if memory.UsagePeak > 0 {
-                       value, err = 
c.CGroupGet("memory.memsw.max_usage_in_bytes")
+                       value, err = 
c.CGroupGetV1("memory.memsw.max_usage_in_bytes")
                        valueInt, err1 = strconv.ParseInt(value, 10, 64)
                        if err == nil && err1 == nil {
                                memory.SwapUsagePeak = valueInt - 
memory.UsagePeak
@@ -5905,7 +5947,7 @@ func (c *containerLXC) processesState() int64 {
        }
 
        if c.state.OS.CGroupPidsController {
-               value, err := c.CGroupGet("pids.current")
+               value, err := c.CGroupGet(cgroup.PidsCurrent)
                if err != nil {
                        return -1
                }
@@ -6527,7 +6569,7 @@ func (c *containerLXC) setNetworkPriority() error {
        success := false
        var last_error error
        for _, netif := range netifs {
-               err = c.CGroupSet("net_prio.ifpriomap", fmt.Sprintf("%s %d", 
netif.Name, networkInt))
+               err = c.CGroupSetV1("net_prio.ifpriomap", fmt.Sprintf("%s %d", 
netif.Name, networkInt))
                if err == nil {
                        success = true
                } else {
diff --git a/lxd/devices.go b/lxd/devices.go
index fb8a84f733..28d4d3a34d 100644
--- a/lxd/devices.go
+++ b/lxd/devices.go
@@ -400,7 +400,7 @@ func deviceTaskBalance(s *state.State) {
                }
 
                sort.Strings(set)
-               err := ctn.CGroupSet("cpuset.cpus", strings.Join(set, ","))
+               err := ctn.CGroupSetV1("cpuset.cpus", strings.Join(set, ","))
                if err != nil {
                        logger.Error("balance: Unable to set cpuset", 
log.Ctx{"name": ctn.Name(), "err": err, "value": strings.Join(set, ",")})
                }
@@ -431,7 +431,7 @@ func deviceNetworkPriority(s *state.State, netif string) {
                }
 
                // Set the value for the new interface
-               c.CGroupSet("net_prio.ifpriomap", fmt.Sprintf("%s %d", netif, 
networkInt))
+               c.CGroupSetV1("net_prio.ifpriomap", fmt.Sprintf("%s %d", netif, 
networkInt))
        }
 
        return
diff --git a/lxd/instance/instance_interface.go 
b/lxd/instance/instance_interface.go
index 9c56b0ddfe..22facc7540 100644
--- a/lxd/instance/instance_interface.go
+++ b/lxd/instance/instance_interface.go
@@ -6,6 +6,7 @@ import (
        "time"
 
        "github.com/lxc/lxd/lxd/backup"
+       "github.com/lxc/lxd/lxd/cgroup"
        "github.com/lxc/lxd/lxd/db"
        deviceConfig "github.com/lxc/lxd/lxd/device/config"
        "github.com/lxc/lxd/lxd/instance/instancetype"
@@ -40,8 +41,10 @@ type Instance interface {
        Export(w io.Writer, properties map[string]string) error
 
        // Live configuration
-       CGroupGet(key string) (string, error)
-       CGroupSet(key string, value string) error
+       CGroupGet(property cgroup.Property) (string, error)
+       CGroupGetV1(key string) (string, error)
+       CGroupSet(property cgroup.Property, value string) error
+       CGroupSetV1(key string, value string) error
        VolatileSet(changes map[string]string) error
 
        // File handling
diff --git a/lxd/instance/qemu/vm_qemu.go b/lxd/instance/qemu/vm_qemu.go
index 5f149794b2..3d456201f2 100644
--- a/lxd/instance/qemu/vm_qemu.go
+++ b/lxd/instance/qemu/vm_qemu.go
@@ -23,6 +23,7 @@ import (
 
        lxdClient "github.com/lxc/lxd/client"
        "github.com/lxc/lxd/lxd/backup"
+       "github.com/lxc/lxd/lxd/cgroup"
        "github.com/lxc/lxd/lxd/cluster"
        "github.com/lxc/lxd/lxd/db"
        "github.com/lxc/lxd/lxd/db/query"
@@ -2208,16 +2209,26 @@ func (vm *Qemu) Export(w io.Writer, properties 
map[string]string) error {
        return fmt.Errorf("Export Not implemented")
 }
 
-// CGroupGet is not implemented for VMs.
-func (vm *Qemu) CGroupGet(key string) (string, error) {
+// CGroupGetV1 is not implemented for VMs.
+func (vm *Qemu) CGroupGet(property cgroup.Property) (string, error) {
        return "", fmt.Errorf("CGroupGet Not implemented")
 }
 
+// CGroupGetV1 is not implemented for VMs.
+func (vm *Qemu) CGroupGetV1(key string) (string, error) {
+       return "", fmt.Errorf("CGroupGetV1 Not implemented")
+}
+
 // CGroupSet is not implemented for VMs.
-func (vm *Qemu) CGroupSet(key string, value string) error {
+func (vm *Qemu) CGroupSet(property cgroup.Property, value string) error {
        return fmt.Errorf("CGroupSet Not implemented")
 }
 
+// CGroupSetV1 is not implemented for VMs.
+func (vm *Qemu) CGroupSetV1(key string, value string) error {
+       return fmt.Errorf("CGroupSetV1 Not implemented")
+}
+
 // VolatileSet sets one or more volatile config keys.
 func (vm *Qemu) VolatileSet(changes map[string]string) error {
        // Sanity check.
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to