mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Break down groups into subsystems
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
parent
06db0604e5
commit
e92f2fd395
9 changed files with 247 additions and 172 deletions
|
@ -10,9 +10,28 @@ import (
|
|||
"github.com/dotcloud/docker/pkg/cgroups"
|
||||
)
|
||||
|
||||
type rawCgroup struct {
|
||||
var (
|
||||
subsystems = []subsystem{
|
||||
&devicesGroup{},
|
||||
&memoryGroup{},
|
||||
&cpuGroup{},
|
||||
&cpusetGroup{},
|
||||
&cpuacctGroup{},
|
||||
&blkioGroup{},
|
||||
&perfEventGroup{},
|
||||
&freezerGroup{},
|
||||
}
|
||||
)
|
||||
|
||||
type subsystem interface {
|
||||
Set(*data) error
|
||||
}
|
||||
|
||||
type data struct {
|
||||
root string
|
||||
cgroup string
|
||||
c *cgroups.Cgroup
|
||||
pid int
|
||||
}
|
||||
|
||||
func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
|
||||
|
@ -38,29 +57,21 @@ func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
|
|||
cgroup = filepath.Join(c.Parent, cgroup)
|
||||
}
|
||||
|
||||
raw := &rawCgroup{
|
||||
d := &data{
|
||||
root: cgroupRoot,
|
||||
cgroup: cgroup,
|
||||
c: c,
|
||||
pid: pid,
|
||||
}
|
||||
for _, g := range []func(*cgroups.Cgroup, int) error{
|
||||
raw.setupDevices,
|
||||
raw.setupMemory,
|
||||
raw.setupCpu,
|
||||
raw.setupCpuset,
|
||||
raw.setupCpuacct,
|
||||
raw.setupBlkio,
|
||||
raw.setupPerfevent,
|
||||
raw.setupFreezer,
|
||||
} {
|
||||
if err := g(c, pid); err != nil {
|
||||
for _, sys := range subsystems {
|
||||
if err := sys.Set(d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return raw, nil
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (raw *rawCgroup) path(subsystem string) (string, error) {
|
||||
func (raw *data) path(subsystem string) (string, error) {
|
||||
initPath, err := cgroups.GetInitCgroupDir(subsystem)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -68,7 +79,7 @@ func (raw *rawCgroup) path(subsystem string) (string, error) {
|
|||
return filepath.Join(raw.root, subsystem, initPath, raw.cgroup), nil
|
||||
}
|
||||
|
||||
func (raw *rawCgroup) join(subsystem string, pid int) (string, error) {
|
||||
func (raw *data) join(subsystem string) (string, error) {
|
||||
path, err := raw.path(subsystem)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -76,166 +87,13 @@ func (raw *rawCgroup) join(subsystem string, pid int) (string, error) {
|
|||
if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
|
||||
return "", err
|
||||
}
|
||||
if err := writeFile(path, "cgroup.procs", strconv.Itoa(pid)); err != nil {
|
||||
if err := writeFile(path, "cgroup.procs", strconv.Itoa(raw.pid)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return path, nil
|
||||
}
|
||||
|
||||
func (raw *rawCgroup) setupDevices(c *cgroups.Cgroup, pid int) (err error) {
|
||||
dir, err := raw.join("devices", pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
os.RemoveAll(dir)
|
||||
}
|
||||
}()
|
||||
|
||||
if !c.DeviceAccess {
|
||||
|
||||
if err := writeFile(dir, "devices.deny", "a"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
allow := []string{
|
||||
// allow mknod for any device
|
||||
"c *:* m",
|
||||
"b *:* m",
|
||||
|
||||
// /dev/null, zero, full
|
||||
"c 1:3 rwm",
|
||||
"c 1:5 rwm",
|
||||
"c 1:7 rwm",
|
||||
|
||||
// consoles
|
||||
"c 5:1 rwm",
|
||||
"c 5:0 rwm",
|
||||
"c 4:0 rwm",
|
||||
"c 4:1 rwm",
|
||||
|
||||
// /dev/urandom,/dev/random
|
||||
"c 1:9 rwm",
|
||||
"c 1:8 rwm",
|
||||
|
||||
// /dev/pts/ - pts namespaces are "coming soon"
|
||||
"c 136:* rwm",
|
||||
"c 5:2 rwm",
|
||||
|
||||
// tuntap
|
||||
"c 10:200 rwm",
|
||||
}
|
||||
|
||||
for _, val := range allow {
|
||||
if err := writeFile(dir, "devices.allow", val); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (raw *rawCgroup) setupMemory(c *cgroups.Cgroup, pid int) (err error) {
|
||||
dir, err := raw.join("memory", pid)
|
||||
// only return an error for memory if it was not specified
|
||||
if err != nil && (c.Memory != 0 || c.MemorySwap != 0) {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
os.RemoveAll(dir)
|
||||
}
|
||||
}()
|
||||
|
||||
if c.Memory != 0 || c.MemorySwap != 0 {
|
||||
if c.Memory != 0 {
|
||||
if err := writeFile(dir, "memory.limit_in_bytes", strconv.FormatInt(c.Memory, 10)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeFile(dir, "memory.soft_limit_in_bytes", strconv.FormatInt(c.Memory, 10)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// By default, MemorySwap is set to twice the size of RAM.
|
||||
// If you want to omit MemorySwap, set it to `-1'.
|
||||
if c.MemorySwap != -1 {
|
||||
if err := writeFile(dir, "memory.memsw.limit_in_bytes", strconv.FormatInt(c.Memory*2, 10)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (raw *rawCgroup) setupCpu(c *cgroups.Cgroup, pid int) (err error) {
|
||||
// We always want to join the cpu group, to allow fair cpu scheduling
|
||||
// on a container basis
|
||||
dir, err := raw.join("cpu", pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.CpuShares != 0 {
|
||||
if err := writeFile(dir, "cpu.shares", strconv.FormatInt(c.CpuShares, 10)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (raw *rawCgroup) setupCpuset(c *cgroups.Cgroup, pid int) (err error) {
|
||||
// we don't want to join this cgroup unless it is specified
|
||||
if c.CpusetCpus != "" {
|
||||
dir, err := raw.join("cpuset", pid)
|
||||
if err != nil && c.CpusetCpus != "" {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
os.RemoveAll(dir)
|
||||
}
|
||||
}()
|
||||
|
||||
if err := writeFile(dir, "cpuset.cpus", c.CpusetCpus); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (raw *rawCgroup) setupCpuacct(c *cgroups.Cgroup, pid int) error {
|
||||
// we just want to join this group even though we don't set anything
|
||||
if _, err := raw.join("cpuacct", pid); err != nil && err != cgroups.ErrNotFound {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (raw *rawCgroup) setupBlkio(c *cgroups.Cgroup, pid int) error {
|
||||
// we just want to join this group even though we don't set anything
|
||||
if _, err := raw.join("blkio", pid); err != nil && err != cgroups.ErrNotFound {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (raw *rawCgroup) setupPerfevent(c *cgroups.Cgroup, pid int) error {
|
||||
// we just want to join this group even though we don't set anything
|
||||
if _, err := raw.join("perf_event", pid); err != nil && err != cgroups.ErrNotFound {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (raw *rawCgroup) setupFreezer(c *cgroups.Cgroup, pid int) error {
|
||||
// we just want to join this group even though we don't set anything
|
||||
if _, err := raw.join("freezer", pid); err != nil && err != cgroups.ErrNotFound {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (raw *rawCgroup) Cleanup() error {
|
||||
func (raw *data) Cleanup() error {
|
||||
get := func(subsystem string) string {
|
||||
path, _ := raw.path(subsystem)
|
||||
return path
|
||||
|
|
16
pkg/cgroups/fs/blkio.go
Normal file
16
pkg/cgroups/fs/blkio.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package fs
|
||||
|
||||
import (
|
||||
"github.com/dotcloud/docker/pkg/cgroups"
|
||||
)
|
||||
|
||||
type blkioGroup struct {
|
||||
}
|
||||
|
||||
func (s *blkioGroup) Set(d *data) error {
|
||||
// we just want to join this group even though we don't set anything
|
||||
if _, err := d.join("blkio"); err != nil && err != cgroups.ErrNotFound {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
23
pkg/cgroups/fs/cpu.go
Normal file
23
pkg/cgroups/fs/cpu.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package fs
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type cpuGroup struct {
|
||||
}
|
||||
|
||||
func (s *cpuGroup) Set(d *data) error {
|
||||
// We always want to join the cpu group, to allow fair cpu scheduling
|
||||
// on a container basis
|
||||
dir, err := d.join("cpu")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.c.CpuShares != 0 {
|
||||
if err := writeFile(dir, "cpu.shares", strconv.FormatInt(d.c.CpuShares, 10)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
16
pkg/cgroups/fs/cpuacct.go
Normal file
16
pkg/cgroups/fs/cpuacct.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package fs
|
||||
|
||||
import (
|
||||
"github.com/dotcloud/docker/pkg/cgroups"
|
||||
)
|
||||
|
||||
type cpuacctGroup struct {
|
||||
}
|
||||
|
||||
func (s *cpuacctGroup) Set(d *data) error {
|
||||
// we just want to join this group even though we don't set anything
|
||||
if _, err := d.join("cpuacct"); err != nil && err != cgroups.ErrNotFound {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
28
pkg/cgroups/fs/cpuset.go
Normal file
28
pkg/cgroups/fs/cpuset.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package fs
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
type cpusetGroup struct {
|
||||
}
|
||||
|
||||
func (s *cpusetGroup) Set(d *data) error {
|
||||
// we don't want to join this cgroup unless it is specified
|
||||
if d.c.CpusetCpus != "" {
|
||||
dir, err := d.join("cpuset")
|
||||
if err != nil && d.c.CpusetCpus != "" {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
os.RemoveAll(dir)
|
||||
}
|
||||
}()
|
||||
|
||||
if err := writeFile(dir, "cpuset.cpus", d.c.CpusetCpus); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
61
pkg/cgroups/fs/devices.go
Normal file
61
pkg/cgroups/fs/devices.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package fs
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
type devicesGroup struct {
|
||||
}
|
||||
|
||||
func (s *devicesGroup) Set(d *data) error {
|
||||
dir, err := d.join("devices")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
os.RemoveAll(dir)
|
||||
}
|
||||
}()
|
||||
|
||||
if !d.c.DeviceAccess {
|
||||
if err := writeFile(dir, "devices.deny", "a"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
allow := []string{
|
||||
// allow mknod for any device
|
||||
"c *:* m",
|
||||
"b *:* m",
|
||||
|
||||
// /dev/null, zero, full
|
||||
"c 1:3 rwm",
|
||||
"c 1:5 rwm",
|
||||
"c 1:7 rwm",
|
||||
|
||||
// consoles
|
||||
"c 5:1 rwm",
|
||||
"c 5:0 rwm",
|
||||
"c 4:0 rwm",
|
||||
"c 4:1 rwm",
|
||||
|
||||
// /dev/urandom,/dev/random
|
||||
"c 1:9 rwm",
|
||||
"c 1:8 rwm",
|
||||
|
||||
// /dev/pts/ - pts namespaces are "coming soon"
|
||||
"c 136:* rwm",
|
||||
"c 5:2 rwm",
|
||||
|
||||
// tuntap
|
||||
"c 10:200 rwm",
|
||||
}
|
||||
|
||||
for _, val := range allow {
|
||||
if err := writeFile(dir, "devices.allow", val); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
16
pkg/cgroups/fs/freezer.go
Normal file
16
pkg/cgroups/fs/freezer.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package fs
|
||||
|
||||
import (
|
||||
"github.com/dotcloud/docker/pkg/cgroups"
|
||||
)
|
||||
|
||||
type freezerGroup struct {
|
||||
}
|
||||
|
||||
func (s *freezerGroup) Set(d *data) error {
|
||||
// we just want to join this group even though we don't set anything
|
||||
if _, err := d.join("freezer"); err != nil && err != cgroups.ErrNotFound {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
41
pkg/cgroups/fs/memory.go
Normal file
41
pkg/cgroups/fs/memory.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package fs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type memoryGroup struct {
|
||||
}
|
||||
|
||||
func (s *memoryGroup) Set(d *data) error {
|
||||
dir, err := d.join("memory")
|
||||
// only return an error for memory if it was not specified
|
||||
if err != nil && (d.c.Memory != 0 || d.c.MemorySwap != 0) {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
os.RemoveAll(dir)
|
||||
}
|
||||
}()
|
||||
|
||||
if d.c.Memory != 0 || d.c.MemorySwap != 0 {
|
||||
if d.c.Memory != 0 {
|
||||
if err := writeFile(dir, "memory.limit_in_bytes", strconv.FormatInt(d.c.Memory, 10)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeFile(dir, "memory.soft_limit_in_bytes", strconv.FormatInt(d.c.Memory, 10)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// By default, MemorySwap is set to twice the size of RAM.
|
||||
// If you want to omit MemorySwap, set it to `-1'.
|
||||
if d.c.MemorySwap != -1 {
|
||||
if err := writeFile(dir, "memory.memsw.limit_in_bytes", strconv.FormatInt(d.c.Memory*2, 10)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
16
pkg/cgroups/fs/perf_event.go
Normal file
16
pkg/cgroups/fs/perf_event.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package fs
|
||||
|
||||
import (
|
||||
"github.com/dotcloud/docker/pkg/cgroups"
|
||||
)
|
||||
|
||||
type perfEventGroup struct {
|
||||
}
|
||||
|
||||
func (s *perfEventGroup) Set(d *data) error {
|
||||
// we just want to join this group even though we don't set anything
|
||||
if _, err := d.join("perf_event"); err != nil && err != cgroups.ErrNotFound {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
Loading…
Reference in a new issue