summaryrefslogtreecommitdiff
path: root/vendor/github.com/containerd/cgroups/systemd.go
blob: fd816e32e3fc4745935f728e838bdb91060b2734 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package cgroups

import (
	"fmt"
	"path/filepath"
	"strings"
	"sync"

	systemdDbus "github.com/coreos/go-systemd/dbus"
	"github.com/godbus/dbus"
	specs "github.com/opencontainers/runtime-spec/specs-go"
)

const (
	SystemdDbus  Name = "systemd"
	defaultSlice      = "system.slice"
)

func Systemd() ([]Subsystem, error) {
	root, err := v1MountPoint()
	if err != nil {
		return nil, err
	}
	defaultSubsystems, err := defaults(root)
	if err != nil {
		return nil, err
	}
	s, err := NewSystemd(root)
	if err != nil {
		return nil, err
	}
	// make sure the systemd controller is added first
	return append([]Subsystem{s}, defaultSubsystems...), nil
}

func Slice(slice, name string) Path {
	if slice == "" {
		slice = defaultSlice
	}
	return func(subsystem Name) (string, error) {
		return filepath.Join(slice, unitName(name)), nil
	}
}

func NewSystemd(root string) (*SystemdController, error) {
	return &SystemdController{
		root: root,
	}, nil
}

type SystemdController struct {
	mu   sync.Mutex
	root string
}

func (s *SystemdController) Name() Name {
	return SystemdDbus
}

func (s *SystemdController) Create(path string, resources *specs.LinuxResources) error {
	conn, err := systemdDbus.New()
	if err != nil {
		return err
	}
	defer conn.Close()
	slice, name := splitName(path)
	properties := []systemdDbus.Property{
		systemdDbus.PropDescription(fmt.Sprintf("cgroup %s", name)),
		systemdDbus.PropWants(slice),
		newProperty("DefaultDependencies", false),
		newProperty("Delegate", true),
		newProperty("MemoryAccounting", true),
		newProperty("CPUAccounting", true),
		newProperty("BlockIOAccounting", true),
	}
	ch := make(chan string)
	_, err = conn.StartTransientUnit(name, "replace", properties, ch)
	if err != nil {
		return err
	}
	<-ch
	return nil
}

func (s *SystemdController) Delete(path string) error {
	conn, err := systemdDbus.New()
	if err != nil {
		return err
	}
	defer conn.Close()
	_, name := splitName(path)
	ch := make(chan string)
	_, err = conn.StopUnit(name, "replace", ch)
	if err != nil {
		return err
	}
	<-ch
	return nil
}

func newProperty(name string, units interface{}) systemdDbus.Property {
	return systemdDbus.Property{
		Name:  name,
		Value: dbus.MakeVariant(units),
	}
}

func unitName(name string) string {
	return fmt.Sprintf("%s.slice", name)
}

func splitName(path string) (slice string, unit string) {
	slice, unit = filepath.Split(path)
	return strings.TrimSuffix(slice, "/"), unit
}