Browse code

Move systemd code into pkg Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)

Michael Crosby authored on 2014/04/19 13:30:08
Showing 6 changed files
1 1
deleted file mode 100644
... ...
@@ -1,15 +0,0 @@
1
-// +build !linux
2
-
3
-package cgroups
4
-
5
-import (
6
-	"fmt"
7
-)
8
-
9
-func useSystemd() bool {
10
-	return false
11
-}
12
-
13
-func systemdApply(c *Cgroup, pid int) (ActiveCgroup, error) {
14
-	return nil, fmt.Errorf("Systemd not supported")
15
-}
16 1
deleted file mode 100644
... ...
@@ -1,164 +0,0 @@
1
-// +build linux
2
-
3
-package cgroups
4
-
5
-import (
6
-	"fmt"
7
-	systemd1 "github.com/coreos/go-systemd/dbus"
8
-	"github.com/dotcloud/docker/pkg/systemd"
9
-	"github.com/godbus/dbus"
10
-	"path/filepath"
11
-	"strings"
12
-	"sync"
13
-)
14
-
15
-type systemdCgroup struct {
16
-}
17
-
18
-var (
19
-	connLock              sync.Mutex
20
-	theConn               *systemd1.Conn
21
-	hasStartTransientUnit bool
22
-)
23
-
24
-func useSystemd() bool {
25
-	if !systemd.SdBooted() {
26
-		return false
27
-	}
28
-
29
-	connLock.Lock()
30
-	defer connLock.Unlock()
31
-
32
-	if theConn == nil {
33
-		var err error
34
-		theConn, err = systemd1.New()
35
-		if err != nil {
36
-			return false
37
-		}
38
-
39
-		// Assume we have StartTransientUnit
40
-		hasStartTransientUnit = true
41
-
42
-		// But if we get UnknownMethod error we don't
43
-		if _, err := theConn.StartTransientUnit("test.scope", "invalid"); err != nil {
44
-			if dbusError, ok := err.(dbus.Error); ok {
45
-				if dbusError.Name == "org.freedesktop.DBus.Error.UnknownMethod" {
46
-					hasStartTransientUnit = false
47
-				}
48
-			}
49
-		}
50
-	}
51
-
52
-	return hasStartTransientUnit
53
-}
54
-
55
-type DeviceAllow struct {
56
-	Node        string
57
-	Permissions string
58
-}
59
-
60
-func getIfaceForUnit(unitName string) string {
61
-	if strings.HasSuffix(unitName, ".scope") {
62
-		return "Scope"
63
-	}
64
-	if strings.HasSuffix(unitName, ".service") {
65
-		return "Service"
66
-	}
67
-	return "Unit"
68
-}
69
-
70
-func systemdApply(c *Cgroup, pid int) (ActiveCgroup, error) {
71
-	unitName := c.Parent + "-" + c.Name + ".scope"
72
-	slice := "system.slice"
73
-
74
-	var properties []systemd1.Property
75
-
76
-	for _, v := range c.UnitProperties {
77
-		switch v[0] {
78
-		case "Slice":
79
-			slice = v[1]
80
-		default:
81
-			return nil, fmt.Errorf("Unknown unit propery %s", v[0])
82
-		}
83
-	}
84
-
85
-	properties = append(properties,
86
-		systemd1.Property{"Slice", dbus.MakeVariant(slice)},
87
-		systemd1.Property{"Description", dbus.MakeVariant("docker container " + c.Name)},
88
-		systemd1.Property{"PIDs", dbus.MakeVariant([]uint32{uint32(pid)})})
89
-
90
-	if !c.DeviceAccess {
91
-		properties = append(properties,
92
-			systemd1.Property{"DevicePolicy", dbus.MakeVariant("strict")},
93
-			systemd1.Property{"DeviceAllow", dbus.MakeVariant([]DeviceAllow{
94
-				{"/dev/null", "rwm"},
95
-				{"/dev/zero", "rwm"},
96
-				{"/dev/full", "rwm"},
97
-				{"/dev/random", "rwm"},
98
-				{"/dev/urandom", "rwm"},
99
-				{"/dev/tty", "rwm"},
100
-				{"/dev/console", "rwm"},
101
-				{"/dev/tty0", "rwm"},
102
-				{"/dev/tty1", "rwm"},
103
-				{"/dev/pts/ptmx", "rwm"},
104
-				// There is no way to add /dev/pts/* here atm, so we hack this manually below
105
-				// /dev/pts/* (how to add this?)
106
-				// Same with tuntap, which doesn't exist as a node most of the time
107
-			})})
108
-	}
109
-
110
-	// Always enable accounting, this gets us the same behaviour as the raw implementation,
111
-	// plus the kernel has some problems with joining the memory cgroup at a later time.
112
-	properties = append(properties,
113
-		systemd1.Property{"MemoryAccounting", dbus.MakeVariant(true)},
114
-		systemd1.Property{"CPUAccounting", dbus.MakeVariant(true)})
115
-
116
-	if c.Memory != 0 {
117
-		properties = append(properties,
118
-			systemd1.Property{"MemoryLimit", dbus.MakeVariant(uint64(c.Memory))})
119
-	}
120
-	// TODO: MemorySwap not available in systemd
121
-
122
-	if c.CpuShares != 0 {
123
-		properties = append(properties,
124
-			systemd1.Property{"CPUShares", dbus.MakeVariant(uint64(c.CpuShares))})
125
-	}
126
-
127
-	if _, err := theConn.StartTransientUnit(unitName, "replace", properties...); err != nil {
128
-		return nil, err
129
-	}
130
-
131
-	// To work around the lack of /dev/pts/* support above we need to manually add these
132
-	// so, ask systemd for the cgroup used
133
-	props, err := theConn.GetUnitTypeProperties(unitName, getIfaceForUnit(unitName))
134
-	if err != nil {
135
-		return nil, err
136
-	}
137
-
138
-	cgroup := props["ControlGroup"].(string)
139
-
140
-	if !c.DeviceAccess {
141
-		mountpoint, err := FindCgroupMountpoint("devices")
142
-		if err != nil {
143
-			return nil, err
144
-		}
145
-
146
-		path := filepath.Join(mountpoint, cgroup)
147
-
148
-		// /dev/pts/*
149
-		if err := writeFile(path, "devices.allow", "c 136:* rwm"); err != nil {
150
-			return nil, err
151
-		}
152
-		// tuntap
153
-		if err := writeFile(path, "devices.allow", "c 10:200 rwm"); err != nil {
154
-			return nil, err
155
-		}
156
-	}
157
-
158
-	return &systemdCgroup{}, nil
159
-}
160
-
161
-func (c *systemdCgroup) Cleanup() error {
162
-	// systemd cleans up, we don't need to do anything
163
-	return nil
164
-}
... ...
@@ -24,16 +24,3 @@ type Cgroup struct {
24 24
 type ActiveCgroup interface {
25 25
 	Cleanup() error
26 26
 }
27
-
28
-func Apply(c *Cgroup, pid int) (ActiveCgroup, error) {
29
-	// We have two implementation of cgroups support, one is based on
30
-	// systemd and the dbus api, and one is based on raw cgroup fs operations
31
-	// following the pre-single-writer model docs at:
32
-	// http://www.freedesktop.org/wiki/Software/systemd/PaxControlGroups/
33
-
34
-	if useSystemd() {
35
-		return systemdApply(c, pid)
36
-	} else {
37
-		return rawApply(c, pid)
38
-	}
39
-}
40 27
new file mode 100644
... ...
@@ -0,0 +1,16 @@
0
+// +build !linux
1
+
2
+package systemd
3
+
4
+import (
5
+	"fmt"
6
+	"github.com/dotcloud/docker/pkg/cgroups"
7
+)
8
+
9
+func UseSystemd() bool {
10
+	return false
11
+}
12
+
13
+func systemdApply(c *Cgroup, pid int) (cgroups.ActiveCgroup, error) {
14
+	return nil, fmt.Errorf("Systemd not supported")
15
+}
0 16
new file mode 100644
... ...
@@ -0,0 +1,167 @@
0
+// +build linux
1
+
2
+package systemd
3
+
4
+import (
5
+	"fmt"
6
+	"io/ioutil"
7
+	"path/filepath"
8
+	"strings"
9
+	"sync"
10
+
11
+	systemd1 "github.com/coreos/go-systemd/dbus"
12
+	"github.com/dotcloud/docker/pkg/cgroups"
13
+	"github.com/dotcloud/docker/pkg/systemd"
14
+	"github.com/godbus/dbus"
15
+)
16
+
17
+type systemdCgroup struct {
18
+}
19
+
20
+type DeviceAllow struct {
21
+	Node        string
22
+	Permissions string
23
+}
24
+
25
+var (
26
+	connLock              sync.Mutex
27
+	theConn               *systemd1.Conn
28
+	hasStartTransientUnit bool
29
+)
30
+
31
+func UseSystemd() bool {
32
+	if !systemd.SdBooted() {
33
+		return false
34
+	}
35
+
36
+	connLock.Lock()
37
+	defer connLock.Unlock()
38
+
39
+	if theConn == nil {
40
+		var err error
41
+		theConn, err = systemd1.New()
42
+		if err != nil {
43
+			return false
44
+		}
45
+
46
+		// Assume we have StartTransientUnit
47
+		hasStartTransientUnit = true
48
+
49
+		// But if we get UnknownMethod error we don't
50
+		if _, err := theConn.StartTransientUnit("test.scope", "invalid"); err != nil {
51
+			if dbusError, ok := err.(dbus.Error); ok {
52
+				if dbusError.Name == "org.freedesktop.DBus.Error.UnknownMethod" {
53
+					hasStartTransientUnit = false
54
+				}
55
+			}
56
+		}
57
+	}
58
+	return hasStartTransientUnit
59
+}
60
+
61
+func getIfaceForUnit(unitName string) string {
62
+	if strings.HasSuffix(unitName, ".scope") {
63
+		return "Scope"
64
+	}
65
+	if strings.HasSuffix(unitName, ".service") {
66
+		return "Service"
67
+	}
68
+	return "Unit"
69
+}
70
+
71
+func Apply(c *cgroups.Cgroup, pid int) (cgroups.ActiveCgroup, error) {
72
+	var (
73
+		unitName   = c.Parent + "-" + c.Name + ".scope"
74
+		slice      = "system.slice"
75
+		properties []systemd1.Property
76
+	)
77
+
78
+	for _, v := range c.UnitProperties {
79
+		switch v[0] {
80
+		case "Slice":
81
+			slice = v[1]
82
+		default:
83
+			return nil, fmt.Errorf("Unknown unit propery %s", v[0])
84
+		}
85
+	}
86
+
87
+	properties = append(properties,
88
+		systemd1.Property{"Slice", dbus.MakeVariant(slice)},
89
+		systemd1.Property{"Description", dbus.MakeVariant("docker container " + c.Name)},
90
+		systemd1.Property{"PIDs", dbus.MakeVariant([]uint32{uint32(pid)})},
91
+	)
92
+
93
+	if !c.DeviceAccess {
94
+		properties = append(properties,
95
+			systemd1.Property{"DevicePolicy", dbus.MakeVariant("strict")},
96
+			systemd1.Property{"DeviceAllow", dbus.MakeVariant([]DeviceAllow{
97
+				{"/dev/null", "rwm"},
98
+				{"/dev/zero", "rwm"},
99
+				{"/dev/full", "rwm"},
100
+				{"/dev/random", "rwm"},
101
+				{"/dev/urandom", "rwm"},
102
+				{"/dev/tty", "rwm"},
103
+				{"/dev/console", "rwm"},
104
+				{"/dev/tty0", "rwm"},
105
+				{"/dev/tty1", "rwm"},
106
+				{"/dev/pts/ptmx", "rwm"},
107
+				// There is no way to add /dev/pts/* here atm, so we hack this manually below
108
+				// /dev/pts/* (how to add this?)
109
+				// Same with tuntap, which doesn't exist as a node most of the time
110
+			})})
111
+	}
112
+
113
+	// Always enable accounting, this gets us the same behaviour as the raw implementation,
114
+	// plus the kernel has some problems with joining the memory cgroup at a later time.
115
+	properties = append(properties,
116
+		systemd1.Property{"MemoryAccounting", dbus.MakeVariant(true)},
117
+		systemd1.Property{"CPUAccounting", dbus.MakeVariant(true)})
118
+
119
+	if c.Memory != 0 {
120
+		properties = append(properties,
121
+			systemd1.Property{"MemoryLimit", dbus.MakeVariant(uint64(c.Memory))})
122
+	}
123
+	// TODO: MemorySwap not available in systemd
124
+
125
+	if c.CpuShares != 0 {
126
+		properties = append(properties,
127
+			systemd1.Property{"CPUShares", dbus.MakeVariant(uint64(c.CpuShares))})
128
+	}
129
+
130
+	if _, err := theConn.StartTransientUnit(unitName, "replace", properties...); err != nil {
131
+		return nil, err
132
+	}
133
+
134
+	// To work around the lack of /dev/pts/* support above we need to manually add these
135
+	// so, ask systemd for the cgroup used
136
+	props, err := theConn.GetUnitTypeProperties(unitName, getIfaceForUnit(unitName))
137
+	if err != nil {
138
+		return nil, err
139
+	}
140
+
141
+	cgroup := props["ControlGroup"].(string)
142
+
143
+	if !c.DeviceAccess {
144
+		mountpoint, err := cgroups.FindCgroupMountpoint("devices")
145
+		if err != nil {
146
+			return nil, err
147
+		}
148
+
149
+		path := filepath.Join(mountpoint, cgroup)
150
+
151
+		// /dev/pts/*
152
+		if err := ioutil.WriteFile(filepath.Join(path, "devices.allow"), []byte("c 136:* rwm"), 0700); err != nil {
153
+			return nil, err
154
+		}
155
+		// tuntap
156
+		if err := ioutil.WriteFile(filepath.Join(path, "devices.allow"), []byte("c 10:200 rwm"), 0700); err != nil {
157
+			return nil, err
158
+		}
159
+	}
160
+	return &systemdCgroup{}, nil
161
+}
162
+
163
+func (c *systemdCgroup) Cleanup() error {
164
+	// systemd cleans up, we don't need to do anything
165
+	return nil
166
+}
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"syscall"
9 9
 
10 10
 	"github.com/dotcloud/docker/pkg/cgroups"
11
+	"github.com/dotcloud/docker/pkg/cgroups/systemd"
11 12
 	"github.com/dotcloud/docker/pkg/libcontainer"
12 13
 	"github.com/dotcloud/docker/pkg/libcontainer/network"
13 14
 	"github.com/dotcloud/docker/pkg/system"
... ...
@@ -99,7 +100,11 @@ func (ns *linuxNs) Exec(container *libcontainer.Container, term Terminal, args [
99 99
 
100 100
 func (ns *linuxNs) SetupCgroups(container *libcontainer.Container, nspid int) (cgroups.ActiveCgroup, error) {
101 101
 	if container.Cgroups != nil {
102
-		return cgroups.Apply(container.Cgroups, nspid)
102
+		c := container.Cgroups
103
+		if systemd.UseSystemd() {
104
+			return systemd.Apply(c, nspid)
105
+		}
106
+		return rawApply(c, nspid)
103 107
 	}
104 108
 	return nil, nil
105 109
 }