From 9a7be1b015a1ba79e5480d0ddddfa5954b994507 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Fri, 21 Mar 2014 14:53:47 +0000 Subject: [PATCH] Add cpuset.cpus to cgroups and native driver options Docker-DCO-1.1-Signed-off-by: Michael Crosby (github: crosbymichael) --- pkg/cgroups/cgroups.go | 32 ++++++++++++++--- .../execdriver/native/configuration/parse.go | 35 +++++++++++++++---- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/pkg/cgroups/cgroups.go b/pkg/cgroups/cgroups.go index b40e1a31fa..9d485d1080 100644 --- a/pkg/cgroups/cgroups.go +++ b/pkg/cgroups/cgroups.go @@ -16,10 +16,11 @@ type Cgroup struct { Name string `json:"name,omitempty"` Parent string `json:"parent,omitempty"` - DeviceAccess bool `json:"device_access,omitempty"` // name of parent cgroup or slice - Memory int64 `json:"memory,omitempty"` // Memory limit (in bytes) - MemorySwap int64 `json:"memory_swap,omitempty"` // Total memory usage (memory + swap); set `-1' to disable swap - CpuShares int64 `json:"cpu_shares,omitempty"` // CPU shares (relative weight vs. other containers) + DeviceAccess bool `json:"device_access,omitempty"` // name of parent cgroup or slice + Memory int64 `json:"memory,omitempty"` // Memory limit (in bytes) + MemorySwap int64 `json:"memory_swap,omitempty"` // Total memory usage (memory + swap); set `-1' to disable swap + CpuShares int64 `json:"cpu_shares,omitempty"` // CPU shares (relative weight vs. other containers) + CpusetCpus string `json:"cpuset_cpus,omitempty"` // CPU to use } // https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt @@ -98,6 +99,7 @@ func (c *Cgroup) Cleanup(root string) error { get("memory"), get("devices"), get("cpu"), + get("cpuset"), } { os.RemoveAll(path) } @@ -150,6 +152,9 @@ func (c *Cgroup) Apply(pid int) error { if err := c.setupCpu(cgroupRoot, pid); err != nil { return err } + if err := c.setupCpuset(cgroupRoot, pid); err != nil { + return err + } return nil } @@ -248,3 +253,22 @@ func (c *Cgroup) setupCpu(cgroupRoot string, pid int) (err error) { } return nil } + +func (c *Cgroup) setupCpuset(cgroupRoot string, pid int) (err error) { + if c.CpusetCpus != "" { + dir, err := c.Join(cgroupRoot, "cpuset", pid) + if err != nil { + return err + } + defer func() { + if err != nil { + os.RemoveAll(dir) + } + }() + + if err := writeFile(dir, "cpuset.cpus", c.CpusetCpus); err != nil { + return err + } + } + return nil +} diff --git a/runtime/execdriver/native/configuration/parse.go b/runtime/execdriver/native/configuration/parse.go index 1733b94426..090cb29660 100644 --- a/runtime/execdriver/native/configuration/parse.go +++ b/runtime/execdriver/native/configuration/parse.go @@ -3,6 +3,7 @@ package configuration import ( "fmt" "github.com/dotcloud/docker/pkg/libcontainer" + "github.com/dotcloud/docker/utils" "os/exec" "path/filepath" "strconv" @@ -19,17 +20,40 @@ var actions = map[string]Action{ "ns.drop": dropNamespace, // drop a namespace when cloning "net.join": joinNetNamespace, // join another containers net namespace - // "net.veth.mac": vethMacAddress, // set the mac address for the veth "cgroups.cpu_shares": cpuShares, // set the cpu shares "cgroups.memory": memory, // set the memory limit "cgroups.memory_swap": memorySwap, // set the memory swap limit + "cgroups.cpuset.cpus": cpusetCpus, // set the cpus used "apparmor_profile": apparmorProfile, // set the apparmor profile to apply "fs.readonly": readonlyFs, // make the rootfs of the container read only } +// GetSupportedActions returns a list of all the avaliable actions supported by the driver +// TODO: this should return a description also +func GetSupportedActions() []string { + var ( + i int + out = make([]string, len(actions)) + ) + for k := range actions { + out[i] = k + i++ + } + return out +} + +func cpusetCpus(container *libcontainer.Container, context interface{}, value string) error { + if container.Cgroups == nil { + return fmt.Errorf("cannot set cgroups when they are disabled") + } + container.Cgroups.CpusetCpus = value + + return nil +} + func apparmorProfile(container *libcontainer.Container, context interface{}, value string) error { container.Context["apparmor_profile"] = value return nil @@ -39,7 +63,7 @@ func cpuShares(container *libcontainer.Container, context interface{}, value str if container.Cgroups == nil { return fmt.Errorf("cannot set cgroups when they are disabled") } - v, err := strconv.ParseInt(value, 0, 64) + v, err := strconv.ParseInt(value, 10, 0) if err != nil { return err } @@ -51,7 +75,8 @@ func memory(container *libcontainer.Container, context interface{}, value string if container.Cgroups == nil { return fmt.Errorf("cannot set cgroups when they are disabled") } - v, err := strconv.ParseInt(value, 0, 64) + + v, err := utils.RAMInBytes(value) if err != nil { return err } @@ -138,7 +163,6 @@ func joinNetNamespace(container *libcontainer.Container, context interface{}, va func vethMacAddress(container *libcontainer.Container, context interface{}, value string) error { var veth *libcontainer.Network - for _, network := range container.Networks { if network.Type == "veth" { veth = network @@ -155,8 +179,7 @@ func vethMacAddress(container *libcontainer.Container, context interface{}, valu // configureCustomOptions takes string commands from the user and allows modification of the // container's default configuration. // -// format: <...value> -// i.e: cgroup devices.allow *:* +// TODO: this can be moved to a general utils or parser in pkg func ParseConfiguration(container *libcontainer.Container, running map[string]*exec.Cmd, opts []string) error { for _, opt := range opts { kv := strings.SplitN(opt, "=", 2)