[lxc-devel] [lxd/master] Cgroup package

tomponline on Github lxc-bot at linuxcontainers.org
Mon Oct 7 10:24:22 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 469 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191007/2671b1da/attachment.bin>
-------------- next part --------------
From dc7e4e4845381f21e7d64432d77ffd7695dd92ec Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 7 Oct 2019 11:22:49 +0100
Subject: [PATCH 1/2] lxd/cgroup: Adds cgroup package with CPU task balancing
 functions

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/cgroup/cgroup_cpu.go | 83 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)
 create mode 100644 lxd/cgroup/cgroup_cpu.go

diff --git a/lxd/cgroup/cgroup_cpu.go b/lxd/cgroup/cgroup_cpu.go
new file mode 100644
index 0000000000..e8d6be0530
--- /dev/null
+++ b/lxd/cgroup/cgroup_cpu.go
@@ -0,0 +1,83 @@
+package cgroup
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+// DeviceSchedRebalance channel for scheduling a CPU rebalance.
+var DeviceSchedRebalance = make(chan []string, 2)
+
+// TaskSchedulerTrigger triggers a CPU rebalance.
+func TaskSchedulerTrigger(srcType string, srcName string, srcStatus string) {
+	// Spawn a go routine which then triggers the scheduler
+	select {
+	case DeviceSchedRebalance <- []string{srcType, srcName, srcStatus}:
+	default:
+		// Channel is full, drop the event
+	}
+}
+
+// ParseCPU parses CPU allowances.
+func ParseCPU(cpuAllowance string, cpuPriority string) (string, string, string, error) {
+	var err error
+
+	// Parse priority
+	cpuShares := 0
+	cpuPriorityInt := 10
+	if cpuPriority != "" {
+		cpuPriorityInt, err = strconv.Atoi(cpuPriority)
+		if err != nil {
+			return "", "", "", err
+		}
+	}
+	cpuShares -= 10 - cpuPriorityInt
+
+	// Parse allowance
+	cpuCfsQuota := "-1"
+	cpuCfsPeriod := "100000"
+
+	if cpuAllowance != "" {
+		if strings.HasSuffix(cpuAllowance, "%") {
+			// Percentage based allocation
+			percent, err := strconv.Atoi(strings.TrimSuffix(cpuAllowance, "%"))
+			if err != nil {
+				return "", "", "", err
+			}
+
+			cpuShares += (10 * percent) + 24
+		} else {
+			// Time based allocation
+			fields := strings.SplitN(cpuAllowance, "/", 2)
+			if len(fields) != 2 {
+				return "", "", "", fmt.Errorf("Invalid allowance: %s", cpuAllowance)
+			}
+
+			quota, err := strconv.Atoi(strings.TrimSuffix(fields[0], "ms"))
+			if err != nil {
+				return "", "", "", err
+			}
+
+			period, err := strconv.Atoi(strings.TrimSuffix(fields[1], "ms"))
+			if err != nil {
+				return "", "", "", err
+			}
+
+			// Set limit in ms
+			cpuCfsQuota = fmt.Sprintf("%d", quota*1000)
+			cpuCfsPeriod = fmt.Sprintf("%d", period*1000)
+			cpuShares += 1024
+		}
+	} else {
+		// Default is 100%
+		cpuShares += 1024
+	}
+
+	// Deal with a potential negative score
+	if cpuShares < 0 {
+		cpuShares = 0
+	}
+
+	return fmt.Sprintf("%d", cpuShares), cpuCfsQuota, cpuCfsPeriod, nil
+}

From f7a2cb7fb5d1193ab4dbfab48830bbc629c534f9 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Mon, 7 Oct 2019 11:23:16 +0100
Subject: [PATCH 2/2] lxd: Updates to use cgroup package

Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
 lxd/container_lxc.go | 13 ++++----
 lxd/devices.go       | 76 ++------------------------------------------
 2 files changed, 9 insertions(+), 80 deletions(-)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index f2c7195b69..ea9819c744 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -26,6 +26,7 @@ import (
 	yaml "gopkg.in/yaml.v2"
 
 	"github.com/lxc/lxd/lxd/apparmor"
+	"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"
@@ -1326,7 +1327,7 @@ func (c *containerLXC) initLXC(config bool) error {
 	cpuAllowance := c.expandedConfig["limits.cpu.allowance"]
 
 	if (cpuPriority != "" || cpuAllowance != "") && c.state.OS.CGroupCPUController {
-		cpuShares, cpuCfsQuota, cpuCfsPeriod, err := deviceParseCPU(cpuAllowance, cpuPriority)
+		cpuShares, cpuCfsQuota, cpuCfsPeriod, err := cgroup.ParseCPU(cpuAllowance, cpuPriority)
 		if err != nil {
 			return err
 		}
@@ -2612,7 +2613,7 @@ func (c *containerLXC) OnStart() error {
 	}
 
 	// Trigger a rebalance
-	deviceTaskSchedulerTrigger("container", c.name, "started")
+	cgroup.TaskSchedulerTrigger("container", c.name, "started")
 
 	// Apply network priority
 	if c.expandedConfig["limits.network.priority"] != "" {
@@ -2964,7 +2965,7 @@ func (c *containerLXC) OnStop(target string) error {
 		}
 
 		// Trigger a rebalance
-		deviceTaskSchedulerTrigger("container", c.name, "stopped")
+		cgroup.TaskSchedulerTrigger("container", c.name, "stopped")
 
 		// Destroy ephemeral containers
 		if c.ephemeral {
@@ -4126,7 +4127,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
 			}
 			c.cConfig = false
 			c.initLXC(true)
-			deviceTaskSchedulerTrigger("container", c.name, "changed")
+			cgroup.TaskSchedulerTrigger("container", c.name, "changed")
 		}
 	}()
 
@@ -4505,7 +4506,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
 				}
 			} else if key == "limits.cpu" {
 				// Trigger a scheduler re-run
-				deviceTaskSchedulerTrigger("container", c.name, "changed")
+				cgroup.TaskSchedulerTrigger("container", c.name, "changed")
 			} else if key == "limits.cpu.priority" || key == "limits.cpu.allowance" {
 				// Skip if no cpu CGroup
 				if !c.state.OS.CGroupCPUController {
@@ -4513,7 +4514,7 @@ func (c *containerLXC) Update(args db.InstanceArgs, userRequested bool) error {
 				}
 
 				// Apply new CPU limits
-				cpuShares, cpuCfsQuota, cpuCfsPeriod, err := deviceParseCPU(c.expandedConfig["limits.cpu.allowance"], c.expandedConfig["limits.cpu.priority"])
+				cpuShares, cpuCfsQuota, cpuCfsPeriod, err := cgroup.ParseCPU(c.expandedConfig["limits.cpu.allowance"], c.expandedConfig["limits.cpu.priority"])
 				if err != nil {
 					return err
 				}
diff --git a/lxd/devices.go b/lxd/devices.go
index aeecf4a69a..6b161e21fd 100644
--- a/lxd/devices.go
+++ b/lxd/devices.go
@@ -14,6 +14,7 @@ import (
 
 	"golang.org/x/sys/unix"
 
+	"github.com/lxc/lxd/lxd/cgroup"
 	"github.com/lxc/lxd/lxd/device"
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/shared"
@@ -22,8 +23,6 @@ import (
 	log "github.com/lxc/lxd/shared/log15"
 )
 
-var deviceSchedRebalance = make(chan []string, 2)
-
 type deviceTaskCPU struct {
 	id    int
 	strId string
@@ -476,7 +475,7 @@ func deviceEventListener(s *state.State) {
 			networkAutoAttach(s.Cluster, e[0])
 		case e := <-chUSB:
 			device.USBRunHandlers(s, &e)
-		case e := <-deviceSchedRebalance:
+		case e := <-cgroup.DeviceSchedRebalance:
 			if len(e) != 3 {
 				logger.Errorf("Scheduler: received an invalid rebalance event")
 				continue
@@ -533,15 +532,6 @@ func devicesRegister(s *state.State) {
 	}
 }
 
-func deviceTaskSchedulerTrigger(srcType string, srcName string, srcStatus string) {
-	// Spawn a go routine which then triggers the scheduler
-	select {
-	case deviceSchedRebalance <- []string{srcType, srcName, srcStatus}:
-	default:
-		// Channel is full, drop the event
-	}
-}
-
 func deviceNextInterfaceHWAddr() (string, error) {
 	// Generate a new random MAC address using the usual prefix
 	ret := bytes.Buffer{}
@@ -559,65 +549,3 @@ func deviceNextInterfaceHWAddr() (string, error) {
 
 	return ret.String(), nil
 }
-
-func deviceParseCPU(cpuAllowance string, cpuPriority string) (string, string, string, error) {
-	var err error
-
-	// Parse priority
-	cpuShares := 0
-	cpuPriorityInt := 10
-	if cpuPriority != "" {
-		cpuPriorityInt, err = strconv.Atoi(cpuPriority)
-		if err != nil {
-			return "", "", "", err
-		}
-	}
-	cpuShares -= 10 - cpuPriorityInt
-
-	// Parse allowance
-	cpuCfsQuota := "-1"
-	cpuCfsPeriod := "100000"
-
-	if cpuAllowance != "" {
-		if strings.HasSuffix(cpuAllowance, "%") {
-			// Percentage based allocation
-			percent, err := strconv.Atoi(strings.TrimSuffix(cpuAllowance, "%"))
-			if err != nil {
-				return "", "", "", err
-			}
-
-			cpuShares += (10 * percent) + 24
-		} else {
-			// Time based allocation
-			fields := strings.SplitN(cpuAllowance, "/", 2)
-			if len(fields) != 2 {
-				return "", "", "", fmt.Errorf("Invalid allowance: %s", cpuAllowance)
-			}
-
-			quota, err := strconv.Atoi(strings.TrimSuffix(fields[0], "ms"))
-			if err != nil {
-				return "", "", "", err
-			}
-
-			period, err := strconv.Atoi(strings.TrimSuffix(fields[1], "ms"))
-			if err != nil {
-				return "", "", "", err
-			}
-
-			// Set limit in ms
-			cpuCfsQuota = fmt.Sprintf("%d", quota*1000)
-			cpuCfsPeriod = fmt.Sprintf("%d", period*1000)
-			cpuShares += 1024
-		}
-	} else {
-		// Default is 100%
-		cpuShares += 1024
-	}
-
-	// Deal with a potential negative score
-	if cpuShares < 0 {
-		cpuShares = 0
-	}
-
-	return fmt.Sprintf("%d", cpuShares), cpuCfsQuota, cpuCfsPeriod, nil
-}


More information about the lxc-devel mailing list