The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6279
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) === Created cgroup package and moves CPU task balancing code out of main package and into cgroup package. This is part of the work to move containerLXC out of main package.
From dc7e4e4845381f21e7d64432d77ffd7695dd92ec Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@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.parr...@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.parr...@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.parr...@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 -}
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel