Browse code

update runc to the latest code base to fix gccgo build Signed-off-by: Srini Brahmaroutu <srbrahma@us.ibm.com>

Srini Brahmaroutu authored on 2016/01/06 07:15:34
Showing 33 changed files
... ...
@@ -139,7 +139,7 @@ func InitContainer(c *Command) *configs.Config {
139 139
 
140 140
 	container.Hostname = getEnv("HOSTNAME", c.ProcessConfig.Env)
141 141
 	container.Cgroups.Name = c.ID
142
-	container.Cgroups.AllowedDevices = c.AllowedDevices
142
+	container.Cgroups.Resources.AllowedDevices = c.AllowedDevices
143 143
 	container.Devices = c.AutoCreatedDevices
144 144
 	container.Rootfs = c.Rootfs
145 145
 	container.Readonlyfs = c.ReadonlyRootfs
... ...
@@ -170,23 +170,23 @@ func getEnv(key string, env []string) string {
170 170
 // SetupCgroups setups cgroup resources for a container.
171 171
 func SetupCgroups(container *configs.Config, c *Command) error {
172 172
 	if c.Resources != nil {
173
-		container.Cgroups.CpuShares = c.Resources.CPUShares
174
-		container.Cgroups.Memory = c.Resources.Memory
175
-		container.Cgroups.MemoryReservation = c.Resources.MemoryReservation
176
-		container.Cgroups.MemorySwap = c.Resources.MemorySwap
177
-		container.Cgroups.KernelMemory = c.Resources.KernelMemory
178
-		container.Cgroups.CpusetCpus = c.Resources.CpusetCpus
179
-		container.Cgroups.CpusetMems = c.Resources.CpusetMems
180
-		container.Cgroups.CpuPeriod = c.Resources.CPUPeriod
181
-		container.Cgroups.CpuQuota = c.Resources.CPUQuota
182
-		container.Cgroups.BlkioWeight = c.Resources.BlkioWeight
183
-		container.Cgroups.BlkioWeightDevice = c.Resources.BlkioWeightDevice
184
-		container.Cgroups.BlkioThrottleReadBpsDevice = c.Resources.BlkioThrottleReadBpsDevice
185
-		container.Cgroups.BlkioThrottleWriteBpsDevice = c.Resources.BlkioThrottleWriteBpsDevice
186
-		container.Cgroups.BlkioThrottleReadIOPSDevice = c.Resources.BlkioThrottleReadIOpsDevice
187
-		container.Cgroups.BlkioThrottleWriteIOPSDevice = c.Resources.BlkioThrottleWriteIOpsDevice
188
-		container.Cgroups.OomKillDisable = c.Resources.OomKillDisable
189
-		container.Cgroups.MemorySwappiness = c.Resources.MemorySwappiness
173
+		container.Cgroups.Resources.CpuShares = c.Resources.CPUShares
174
+		container.Cgroups.Resources.Memory = c.Resources.Memory
175
+		container.Cgroups.Resources.MemoryReservation = c.Resources.MemoryReservation
176
+		container.Cgroups.Resources.MemorySwap = c.Resources.MemorySwap
177
+		container.Cgroups.Resources.KernelMemory = c.Resources.KernelMemory
178
+		container.Cgroups.Resources.CpusetCpus = c.Resources.CpusetCpus
179
+		container.Cgroups.Resources.CpusetMems = c.Resources.CpusetMems
180
+		container.Cgroups.Resources.CpuPeriod = c.Resources.CPUPeriod
181
+		container.Cgroups.Resources.CpuQuota = c.Resources.CPUQuota
182
+		container.Cgroups.Resources.BlkioWeight = c.Resources.BlkioWeight
183
+		container.Cgroups.Resources.BlkioWeightDevice = c.Resources.BlkioWeightDevice
184
+		container.Cgroups.Resources.BlkioThrottleReadBpsDevice = c.Resources.BlkioThrottleReadBpsDevice
185
+		container.Cgroups.Resources.BlkioThrottleWriteBpsDevice = c.Resources.BlkioThrottleWriteBpsDevice
186
+		container.Cgroups.Resources.BlkioThrottleReadIOPSDevice = c.Resources.BlkioThrottleReadIOpsDevice
187
+		container.Cgroups.Resources.BlkioThrottleWriteIOPSDevice = c.Resources.BlkioThrottleWriteIOpsDevice
188
+		container.Cgroups.Resources.OomKillDisable = c.Resources.OomKillDisable
189
+		container.Cgroups.Resources.MemorySwappiness = c.Resources.MemorySwappiness
190 190
 	}
191 191
 
192 192
 	return nil
... ...
@@ -251,7 +251,7 @@ func (d *Driver) setupRemappedRoot(container *configs.Config, c *execdriver.Comm
251 251
 
252 252
 func (d *Driver) setPrivileged(container *configs.Config) (err error) {
253 253
 	container.Capabilities = execdriver.GetAllCapabilities()
254
-	container.Cgroups.AllowAllDevices = true
254
+	container.Cgroups.Resources.AllowAllDevices = true
255 255
 
256 256
 	hostDevices, err := devices.HostDevices()
257 257
 	if err != nil {
... ...
@@ -385,7 +385,7 @@ func (d *Driver) Stats(id string) (*execdriver.ResourceStats, error) {
385 385
 	if err != nil {
386 386
 		return nil, err
387 387
 	}
388
-	memoryLimit := c.Config().Cgroups.Memory
388
+	memoryLimit := c.Config().Cgroups.Resources.Memory
389 389
 	// if the container does not have any memory limit specified set the
390 390
 	// limit to the machines memory
391 391
 	if memoryLimit == 0 {
... ...
@@ -40,9 +40,11 @@ func New() *configs.Config {
40 40
 			{Type: "NEWUSER"},
41 41
 		}),
42 42
 		Cgroups: &configs.Cgroup{
43
-			Parent:           "/docker",
44
-			AllowAllDevices:  false,
45
-			MemorySwappiness: -1,
43
+			Parent: "/docker",
44
+			Resources: &configs.Resources{
45
+				AllowAllDevices:  false,
46
+				MemorySwappiness: -1,
47
+			},
46 48
 		},
47 49
 		Mounts: []*configs.Mount{
48 50
 			{
... ...
@@ -51,7 +51,7 @@ clone git github.com/miekg/pkcs11 80f102b5cac759de406949c47f0928b99bd64cdf
51 51
 clone git github.com/jfrazelle/go v1.5.1-1
52 52
 clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
53 53
 
54
-clone git github.com/opencontainers/runc ba1568de399395774ad84c2ace65937814c542ed # libcontainer
54
+clone git github.com/opencontainers/runc d97d5e8b007e4657316eed76ea30bc0f690230cf # libcontainer
55 55
 clone git github.com/opencontainers/specs 46d949ea81080c5f60dfb72ee91468b1e9fb2998 # specs
56 56
 clone git github.com/seccomp/libseccomp-golang 1b506fc7c24eec5a3693cdcbed40d9c226cfc6a1
57 57
 # libcontainer deps (see src/github.com/opencontainers/runc/Godeps/Godeps.json)
58 58
deleted file mode 100644
... ...
@@ -1,55 +0,0 @@
1
-# Contributing to Docker
2
-
3
-### Sign your work
4
-
5
-The sign-off is a simple line at the end of the explanation for the patch. Your
6
-signature certifies that you wrote the patch or otherwise have the right to pass
7
-it on as an open-source patch. The rules are pretty simple: if you can certify
8
-the below (from [developercertificate.org](http://developercertificate.org/)):
9
-
10
-```
11
-Developer Certificate of Origin
12
-Version 1.1
13
-
14
-Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
15
-660 York Street, Suite 102,
16
-San Francisco, CA 94110 USA
17
-
18
-Everyone is permitted to copy and distribute verbatim copies of this
19
-license document, but changing it is not allowed.
20
-
21
-Developer's Certificate of Origin 1.1
22
-
23
-By making a contribution to this project, I certify that:
24
-
25
-(a) The contribution was created in whole or in part by me and I
26
-    have the right to submit it under the open source license
27
-    indicated in the file; or
28
-
29
-(b) The contribution is based upon previous work that, to the best
30
-    of my knowledge, is covered under an appropriate open source
31
-    license and I have the right under that license to submit that
32
-    work with modifications, whether created in whole or in part
33
-    by me, under the same open source license (unless I am
34
-    permitted to submit under a different license), as indicated
35
-    in the file; or
36
-
37
-(c) The contribution was provided directly to me by some other
38
-    person who certified (a), (b) or (c) and I have not modified
39
-    it.
40
-
41
-(d) I understand and agree that this project and the contribution
42
-    are public and that a record of the contribution (including all
43
-    personal information I submit with it, including my sign-off) is
44
-    maintained indefinitely and may be redistributed consistent with
45
-    this project or the open source license(s) involved.
46
-```
47
-
48
-Then you just add a line to every git commit message:
49
-
50
-    Signed-off-by: Joe Smith <joe.smith@email.com>
51
-
52
-Use your real name (sorry, no pseudonyms or anonymous contributions.)
53
-
54
-If you set your `user.name` and `user.email` git configs, you can sign your
55
-commit automatically with `git commit -s`.
56 1
deleted file mode 100644
... ...
@@ -1,27 +0,0 @@
1
-# go-connections maintainers file
2
-#
3
-# This file describes who runs the docker/go-connections project and how.
4
-# This is a living document - if you see something out of date or missing, speak up!
5
-#
6
-# It is structured to be consumable by both humans and programs.
7
-# To extract its contents programmatically, use any TOML-compliant parser.
8
-#
9
-# This file is compiled into the MAINTAINERS file in docker/opensource.
10
-#
11
-[Org]
12
-	[Org."Core maintainers"]
13
-		people = [
14
-			"calavera",
15
-		]
16
-
17
-[people]
18
-
19
-# A reference list of all people associated with the project.
20
-# All other sections should refer to people by their canonical key
21
-# in the people section.
22
-
23
-	# ADD YOURSELF HERE IN ALPHABETICAL ORDER
24
-	[people.calavera]
25
-	Name = "David Calavera"
26
-	Email = "david.calavera@gmail.com"
27
-	GitHub = "calavera"
28 1
deleted file mode 100644
... ...
@@ -1,13 +0,0 @@
1
-[![GoDoc](https://godoc.org/github.com/docker/go-connections?status.svg)](https://godoc.org/github.com/docker/go-connections)
2
-
3
-# Introduction
4
-
5
-go-connections provides common package to work with network connections.
6
-
7
-## Usage
8
-
9
-See the [docs in godoc](https://godoc.org/github.com/docker/go-connections) for examples and documentation.
10
-
11
-## License
12
-
13
-go-connections is licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for the full license text.
14 1
deleted file mode 100644
... ...
@@ -1,14 +0,0 @@
1
-dependencies:
2
-  pre:
3
-    # setup ipv6
4
-    - sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=0 net.ipv6.conf.default.disable_ipv6=0 net.ipv6.conf.all.disable_ipv6=0
5
-  post:
6
-    # install golint
7
-    - go get github.com/golang/lint/golint
8
-
9
-test:
10
-  pre:
11
-    # run analysis before tests
12
-    - go vet ./...
13
-    - test -z "$(golint ./... | tee /dev/stderr)"
14
-    - test -z "$(gofmt -s -l . | tee /dev/stderr)"
15 1
deleted file mode 100644
... ...
@@ -1,3 +0,0 @@
1
-// Package connections provides libraries to work with network connections.
2
-// This library is divided in several components for specific usage.
3
-package connections
4 1
deleted file mode 100644
... ...
@@ -1,525 +0,0 @@
1
-package nat
2
-
3
-import (
4
-	"testing"
5
-)
6
-
7
-func TestParsePort(t *testing.T) {
8
-	var (
9
-		p   int
10
-		err error
11
-	)
12
-
13
-	p, err = ParsePort("1234")
14
-
15
-	if err != nil || p != 1234 {
16
-		t.Fatal("Parsing '1234' did not succeed")
17
-	}
18
-
19
-	// FIXME currently this is a valid port. I don't think it should be.
20
-	// I'm leaving this test commented out until we make a decision.
21
-	// - erikh
22
-
23
-	/*
24
-		p, err = ParsePort("0123")
25
-
26
-		if err != nil {
27
-		    t.Fatal("Successfully parsed port '0123' to '123'")
28
-		}
29
-	*/
30
-
31
-	p, err = ParsePort("asdf")
32
-
33
-	if err == nil || p != 0 {
34
-		t.Fatal("Parsing port 'asdf' succeeded")
35
-	}
36
-
37
-	p, err = ParsePort("1asdf")
38
-
39
-	if err == nil || p != 0 {
40
-		t.Fatal("Parsing port '1asdf' succeeded")
41
-	}
42
-}
43
-
44
-func TestParsePortRangeToInt(t *testing.T) {
45
-	var (
46
-		begin int
47
-		end   int
48
-		err   error
49
-	)
50
-
51
-	type TestRange struct {
52
-		Range string
53
-		Begin int
54
-		End   int
55
-	}
56
-	validRanges := []TestRange{
57
-		{"1234", 1234, 1234},
58
-		{"1234-1234", 1234, 1234},
59
-		{"1234-1235", 1234, 1235},
60
-		{"8000-9000", 8000, 9000},
61
-		{"0", 0, 0},
62
-		{"0-0", 0, 0},
63
-	}
64
-
65
-	for _, r := range validRanges {
66
-		begin, end, err = ParsePortRangeToInt(r.Range)
67
-
68
-		if err != nil || begin != r.Begin {
69
-			t.Fatalf("Parsing port range '%s' did not succeed. Expected begin %d, got %d", r.Range, r.Begin, begin)
70
-		}
71
-		if err != nil || end != r.End {
72
-			t.Fatalf("Parsing port range '%s' did not succeed. Expected end %d, got %d", r.Range, r.End, end)
73
-		}
74
-	}
75
-
76
-	invalidRanges := []string{
77
-		"asdf",
78
-		"1asdf",
79
-		"9000-8000",
80
-		"9000-",
81
-		"-8000",
82
-		"-8000-",
83
-	}
84
-
85
-	for _, r := range invalidRanges {
86
-		begin, end, err = ParsePortRangeToInt(r)
87
-
88
-		if err == nil || begin != 0 || end != 0 {
89
-			t.Fatalf("Parsing port range '%s' succeeded", r)
90
-		}
91
-	}
92
-}
93
-
94
-func TestPort(t *testing.T) {
95
-	p, err := NewPort("tcp", "1234")
96
-
97
-	if err != nil {
98
-		t.Fatalf("tcp, 1234 had a parsing issue: %v", err)
99
-	}
100
-
101
-	if string(p) != "1234/tcp" {
102
-		t.Fatal("tcp, 1234 did not result in the string 1234/tcp")
103
-	}
104
-
105
-	if p.Proto() != "tcp" {
106
-		t.Fatal("protocol was not tcp")
107
-	}
108
-
109
-	if p.Port() != "1234" {
110
-		t.Fatal("port string value was not 1234")
111
-	}
112
-
113
-	if p.Int() != 1234 {
114
-		t.Fatal("port int value was not 1234")
115
-	}
116
-
117
-	p, err = NewPort("tcp", "asd1234")
118
-	if err == nil {
119
-		t.Fatal("tcp, asd1234 was supposed to fail")
120
-	}
121
-
122
-	p, err = NewPort("tcp", "1234-1230")
123
-	if err == nil {
124
-		t.Fatal("tcp, 1234-1230 was supposed to fail")
125
-	}
126
-
127
-	p, err = NewPort("tcp", "1234-1242")
128
-	if err != nil {
129
-		t.Fatalf("tcp, 1234-1242 had a parsing issue: %v", err)
130
-	}
131
-
132
-	if string(p) != "1234-1242/tcp" {
133
-		t.Fatal("tcp, 1234-1242 did not result in the string 1234-1242/tcp")
134
-	}
135
-}
136
-
137
-func TestSplitProtoPort(t *testing.T) {
138
-	var (
139
-		proto string
140
-		port  string
141
-	)
142
-
143
-	proto, port = SplitProtoPort("1234/tcp")
144
-
145
-	if proto != "tcp" || port != "1234" {
146
-		t.Fatal("Could not split 1234/tcp properly")
147
-	}
148
-
149
-	proto, port = SplitProtoPort("")
150
-
151
-	if proto != "" || port != "" {
152
-		t.Fatal("parsing an empty string yielded surprising results", proto, port)
153
-	}
154
-
155
-	proto, port = SplitProtoPort("1234")
156
-
157
-	if proto != "tcp" || port != "1234" {
158
-		t.Fatal("tcp is not the default protocol for portspec '1234'", proto, port)
159
-	}
160
-
161
-	proto, port = SplitProtoPort("1234/")
162
-
163
-	if proto != "tcp" || port != "1234" {
164
-		t.Fatal("parsing '1234/' yielded:" + port + "/" + proto)
165
-	}
166
-
167
-	proto, port = SplitProtoPort("/tcp")
168
-
169
-	if proto != "" || port != "" {
170
-		t.Fatal("parsing '/tcp' yielded:" + port + "/" + proto)
171
-	}
172
-}
173
-
174
-func TestParsePortSpecs(t *testing.T) {
175
-	var (
176
-		portMap    map[Port]struct{}
177
-		bindingMap map[Port][]PortBinding
178
-		err        error
179
-	)
180
-
181
-	portMap, bindingMap, err = ParsePortSpecs([]string{"1234/tcp", "2345/udp"})
182
-
183
-	if err != nil {
184
-		t.Fatalf("Error while processing ParsePortSpecs: %s", err)
185
-	}
186
-
187
-	if _, ok := portMap[Port("1234/tcp")]; !ok {
188
-		t.Fatal("1234/tcp was not parsed properly")
189
-	}
190
-
191
-	if _, ok := portMap[Port("2345/udp")]; !ok {
192
-		t.Fatal("2345/udp was not parsed properly")
193
-	}
194
-
195
-	for portspec, bindings := range bindingMap {
196
-		if len(bindings) != 1 {
197
-			t.Fatalf("%s should have exactly one binding", portspec)
198
-		}
199
-
200
-		if bindings[0].HostIP != "" {
201
-			t.Fatalf("HostIP should not be set for %s", portspec)
202
-		}
203
-
204
-		if bindings[0].HostPort != "" {
205
-			t.Fatalf("HostPort should not be set for %s", portspec)
206
-		}
207
-	}
208
-
209
-	portMap, bindingMap, err = ParsePortSpecs([]string{"1234:1234/tcp", "2345:2345/udp"})
210
-
211
-	if err != nil {
212
-		t.Fatalf("Error while processing ParsePortSpecs: %s", err)
213
-	}
214
-
215
-	if _, ok := portMap[Port("1234/tcp")]; !ok {
216
-		t.Fatal("1234/tcp was not parsed properly")
217
-	}
218
-
219
-	if _, ok := portMap[Port("2345/udp")]; !ok {
220
-		t.Fatal("2345/udp was not parsed properly")
221
-	}
222
-
223
-	for portspec, bindings := range bindingMap {
224
-		_, port := SplitProtoPort(string(portspec))
225
-
226
-		if len(bindings) != 1 {
227
-			t.Fatalf("%s should have exactly one binding", portspec)
228
-		}
229
-
230
-		if bindings[0].HostIP != "" {
231
-			t.Fatalf("HostIP should not be set for %s", portspec)
232
-		}
233
-
234
-		if bindings[0].HostPort != port {
235
-			t.Fatalf("HostPort should be %s for %s", port, portspec)
236
-		}
237
-	}
238
-
239
-	portMap, bindingMap, err = ParsePortSpecs([]string{"0.0.0.0:1234:1234/tcp", "0.0.0.0:2345:2345/udp"})
240
-
241
-	if err != nil {
242
-		t.Fatalf("Error while processing ParsePortSpecs: %s", err)
243
-	}
244
-
245
-	if _, ok := portMap[Port("1234/tcp")]; !ok {
246
-		t.Fatal("1234/tcp was not parsed properly")
247
-	}
248
-
249
-	if _, ok := portMap[Port("2345/udp")]; !ok {
250
-		t.Fatal("2345/udp was not parsed properly")
251
-	}
252
-
253
-	for portspec, bindings := range bindingMap {
254
-		_, port := SplitProtoPort(string(portspec))
255
-
256
-		if len(bindings) != 1 {
257
-			t.Fatalf("%s should have exactly one binding", portspec)
258
-		}
259
-
260
-		if bindings[0].HostIP != "0.0.0.0" {
261
-			t.Fatalf("HostIP is not 0.0.0.0 for %s", portspec)
262
-		}
263
-
264
-		if bindings[0].HostPort != port {
265
-			t.Fatalf("HostPort should be %s for %s", port, portspec)
266
-		}
267
-	}
268
-
269
-	_, _, err = ParsePortSpecs([]string{"localhost:1234:1234/tcp"})
270
-
271
-	if err == nil {
272
-		t.Fatal("Received no error while trying to parse a hostname instead of ip")
273
-	}
274
-}
275
-
276
-func TestParsePortSpecsWithRange(t *testing.T) {
277
-	var (
278
-		portMap    map[Port]struct{}
279
-		bindingMap map[Port][]PortBinding
280
-		err        error
281
-	)
282
-
283
-	portMap, bindingMap, err = ParsePortSpecs([]string{"1234-1236/tcp", "2345-2347/udp"})
284
-
285
-	if err != nil {
286
-		t.Fatalf("Error while processing ParsePortSpecs: %s", err)
287
-	}
288
-
289
-	if _, ok := portMap[Port("1235/tcp")]; !ok {
290
-		t.Fatal("1234/tcp was not parsed properly")
291
-	}
292
-
293
-	if _, ok := portMap[Port("2346/udp")]; !ok {
294
-		t.Fatal("2345/udp was not parsed properly")
295
-	}
296
-
297
-	for portspec, bindings := range bindingMap {
298
-		if len(bindings) != 1 {
299
-			t.Fatalf("%s should have exactly one binding", portspec)
300
-		}
301
-
302
-		if bindings[0].HostIP != "" {
303
-			t.Fatalf("HostIP should not be set for %s", portspec)
304
-		}
305
-
306
-		if bindings[0].HostPort != "" {
307
-			t.Fatalf("HostPort should not be set for %s", portspec)
308
-		}
309
-	}
310
-
311
-	portMap, bindingMap, err = ParsePortSpecs([]string{"1234-1236:1234-1236/tcp", "2345-2347:2345-2347/udp"})
312
-
313
-	if err != nil {
314
-		t.Fatalf("Error while processing ParsePortSpecs: %s", err)
315
-	}
316
-
317
-	if _, ok := portMap[Port("1235/tcp")]; !ok {
318
-		t.Fatal("1234/tcp was not parsed properly")
319
-	}
320
-
321
-	if _, ok := portMap[Port("2346/udp")]; !ok {
322
-		t.Fatal("2345/udp was not parsed properly")
323
-	}
324
-
325
-	for portspec, bindings := range bindingMap {
326
-		_, port := SplitProtoPort(string(portspec))
327
-		if len(bindings) != 1 {
328
-			t.Fatalf("%s should have exactly one binding", portspec)
329
-		}
330
-
331
-		if bindings[0].HostIP != "" {
332
-			t.Fatalf("HostIP should not be set for %s", portspec)
333
-		}
334
-
335
-		if bindings[0].HostPort != port {
336
-			t.Fatalf("HostPort should be %s for %s", port, portspec)
337
-		}
338
-	}
339
-
340
-	portMap, bindingMap, err = ParsePortSpecs([]string{"0.0.0.0:1234-1236:1234-1236/tcp", "0.0.0.0:2345-2347:2345-2347/udp"})
341
-
342
-	if err != nil {
343
-		t.Fatalf("Error while processing ParsePortSpecs: %s", err)
344
-	}
345
-
346
-	if _, ok := portMap[Port("1235/tcp")]; !ok {
347
-		t.Fatal("1234/tcp was not parsed properly")
348
-	}
349
-
350
-	if _, ok := portMap[Port("2346/udp")]; !ok {
351
-		t.Fatal("2345/udp was not parsed properly")
352
-	}
353
-
354
-	for portspec, bindings := range bindingMap {
355
-		_, port := SplitProtoPort(string(portspec))
356
-		if len(bindings) != 1 || bindings[0].HostIP != "0.0.0.0" || bindings[0].HostPort != port {
357
-			t.Fatalf("Expect single binding to port %s but found %s", port, bindings)
358
-		}
359
-	}
360
-
361
-	_, _, err = ParsePortSpecs([]string{"localhost:1234-1236:1234-1236/tcp"})
362
-
363
-	if err == nil {
364
-		t.Fatal("Received no error while trying to parse a hostname instead of ip")
365
-	}
366
-}
367
-
368
-func TestParseNetworkOptsPrivateOnly(t *testing.T) {
369
-	ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100::80"})
370
-	if err != nil {
371
-		t.Fatal(err)
372
-	}
373
-	if len(ports) != 1 {
374
-		t.Logf("Expected 1 got %d", len(ports))
375
-		t.FailNow()
376
-	}
377
-	if len(bindings) != 1 {
378
-		t.Logf("Expected 1 got %d", len(bindings))
379
-		t.FailNow()
380
-	}
381
-	for k := range ports {
382
-		if k.Proto() != "tcp" {
383
-			t.Logf("Expected tcp got %s", k.Proto())
384
-			t.Fail()
385
-		}
386
-		if k.Port() != "80" {
387
-			t.Logf("Expected 80 got %s", k.Port())
388
-			t.Fail()
389
-		}
390
-		b, exists := bindings[k]
391
-		if !exists {
392
-			t.Log("Binding does not exist")
393
-			t.FailNow()
394
-		}
395
-		if len(b) != 1 {
396
-			t.Logf("Expected 1 got %d", len(b))
397
-			t.FailNow()
398
-		}
399
-		s := b[0]
400
-		if s.HostPort != "" {
401
-			t.Logf("Expected \"\" got %s", s.HostPort)
402
-			t.Fail()
403
-		}
404
-		if s.HostIP != "192.168.1.100" {
405
-			t.Fail()
406
-		}
407
-	}
408
-}
409
-
410
-func TestParseNetworkOptsPublic(t *testing.T) {
411
-	ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100:8080:80"})
412
-	if err != nil {
413
-		t.Fatal(err)
414
-	}
415
-	if len(ports) != 1 {
416
-		t.Logf("Expected 1 got %d", len(ports))
417
-		t.FailNow()
418
-	}
419
-	if len(bindings) != 1 {
420
-		t.Logf("Expected 1 got %d", len(bindings))
421
-		t.FailNow()
422
-	}
423
-	for k := range ports {
424
-		if k.Proto() != "tcp" {
425
-			t.Logf("Expected tcp got %s", k.Proto())
426
-			t.Fail()
427
-		}
428
-		if k.Port() != "80" {
429
-			t.Logf("Expected 80 got %s", k.Port())
430
-			t.Fail()
431
-		}
432
-		b, exists := bindings[k]
433
-		if !exists {
434
-			t.Log("Binding does not exist")
435
-			t.FailNow()
436
-		}
437
-		if len(b) != 1 {
438
-			t.Logf("Expected 1 got %d", len(b))
439
-			t.FailNow()
440
-		}
441
-		s := b[0]
442
-		if s.HostPort != "8080" {
443
-			t.Logf("Expected 8080 got %s", s.HostPort)
444
-			t.Fail()
445
-		}
446
-		if s.HostIP != "192.168.1.100" {
447
-			t.Fail()
448
-		}
449
-	}
450
-}
451
-
452
-func TestParseNetworkOptsPublicNoPort(t *testing.T) {
453
-	ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100"})
454
-
455
-	if err == nil {
456
-		t.Logf("Expected error Invalid containerPort")
457
-		t.Fail()
458
-	}
459
-	if ports != nil {
460
-		t.Logf("Expected nil got %s", ports)
461
-		t.Fail()
462
-	}
463
-	if bindings != nil {
464
-		t.Logf("Expected nil got %s", bindings)
465
-		t.Fail()
466
-	}
467
-}
468
-
469
-func TestParseNetworkOptsNegativePorts(t *testing.T) {
470
-	ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100:-1:-1"})
471
-
472
-	if err == nil {
473
-		t.Fail()
474
-	}
475
-	if len(ports) != 0 {
476
-		t.Logf("Expected nil got %d", len(ports))
477
-		t.Fail()
478
-	}
479
-	if len(bindings) != 0 {
480
-		t.Logf("Expected 0 got %d", len(bindings))
481
-		t.Fail()
482
-	}
483
-}
484
-
485
-func TestParseNetworkOptsUdp(t *testing.T) {
486
-	ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100::6000/udp"})
487
-	if err != nil {
488
-		t.Fatal(err)
489
-	}
490
-	if len(ports) != 1 {
491
-		t.Logf("Expected 1 got %d", len(ports))
492
-		t.FailNow()
493
-	}
494
-	if len(bindings) != 1 {
495
-		t.Logf("Expected 1 got %d", len(bindings))
496
-		t.FailNow()
497
-	}
498
-	for k := range ports {
499
-		if k.Proto() != "udp" {
500
-			t.Logf("Expected udp got %s", k.Proto())
501
-			t.Fail()
502
-		}
503
-		if k.Port() != "6000" {
504
-			t.Logf("Expected 6000 got %s", k.Port())
505
-			t.Fail()
506
-		}
507
-		b, exists := bindings[k]
508
-		if !exists {
509
-			t.Log("Binding does not exist")
510
-			t.FailNow()
511
-		}
512
-		if len(b) != 1 {
513
-			t.Logf("Expected 1 got %d", len(b))
514
-			t.FailNow()
515
-		}
516
-		s := b[0]
517
-		if s.HostPort != "" {
518
-			t.Logf("Expected \"\" got %s", s.HostPort)
519
-			t.Fail()
520
-		}
521
-		if s.HostIP != "192.168.1.100" {
522
-			t.Fail()
523
-		}
524
-	}
525
-}
526 1
deleted file mode 100644
... ...
@@ -1,54 +0,0 @@
1
-package nat
2
-
3
-import (
4
-	"strings"
5
-	"testing"
6
-)
7
-
8
-func TestParsePortRange(t *testing.T) {
9
-	if start, end, err := ParsePortRange("8000-8080"); err != nil || start != 8000 || end != 8080 {
10
-		t.Fatalf("Error: %s or Expecting {start,end} values {8000,8080} but found {%d,%d}.", err, start, end)
11
-	}
12
-}
13
-
14
-func TestParsePortRangeEmpty(t *testing.T) {
15
-	if _, _, err := ParsePortRange(""); err == nil || err.Error() != "Empty string specified for ports." {
16
-		t.Fatalf("Expected error 'Empty string specified for ports.', got %v", err)
17
-	}
18
-}
19
-
20
-func TestParsePortRangeWithNoRange(t *testing.T) {
21
-	start, end, err := ParsePortRange("8080")
22
-	if err != nil {
23
-		t.Fatal(err)
24
-	}
25
-	if start != 8080 || end != 8080 {
26
-		t.Fatalf("Expected start and end to be the same and equal to 8080, but were %v and %v", start, end)
27
-	}
28
-}
29
-
30
-func TestParsePortRangeIncorrectRange(t *testing.T) {
31
-	if _, _, err := ParsePortRange("9000-8080"); err == nil || !strings.Contains(err.Error(), "Invalid range specified for the Port") {
32
-		t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
33
-	}
34
-}
35
-
36
-func TestParsePortRangeIncorrectEndRange(t *testing.T) {
37
-	if _, _, err := ParsePortRange("8000-a"); err == nil || !strings.Contains(err.Error(), "invalid syntax") {
38
-		t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
39
-	}
40
-
41
-	if _, _, err := ParsePortRange("8000-30a"); err == nil || !strings.Contains(err.Error(), "invalid syntax") {
42
-		t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
43
-	}
44
-}
45
-
46
-func TestParsePortRangeIncorrectStartRange(t *testing.T) {
47
-	if _, _, err := ParsePortRange("a-8000"); err == nil || !strings.Contains(err.Error(), "invalid syntax") {
48
-		t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
49
-	}
50
-
51
-	if _, _, err := ParsePortRange("30a-8000"); err == nil || !strings.Contains(err.Error(), "invalid syntax") {
52
-		t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
53
-	}
54
-}
55 1
deleted file mode 100644
... ...
@@ -1,85 +0,0 @@
1
-package nat
2
-
3
-import (
4
-	"fmt"
5
-	"reflect"
6
-	"testing"
7
-)
8
-
9
-func TestSortUniquePorts(t *testing.T) {
10
-	ports := []Port{
11
-		Port("6379/tcp"),
12
-		Port("22/tcp"),
13
-	}
14
-
15
-	Sort(ports, func(ip, jp Port) bool {
16
-		return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp")
17
-	})
18
-
19
-	first := ports[0]
20
-	if fmt.Sprint(first) != "22/tcp" {
21
-		t.Log(fmt.Sprint(first))
22
-		t.Fail()
23
-	}
24
-}
25
-
26
-func TestSortSamePortWithDifferentProto(t *testing.T) {
27
-	ports := []Port{
28
-		Port("8888/tcp"),
29
-		Port("8888/udp"),
30
-		Port("6379/tcp"),
31
-		Port("6379/udp"),
32
-	}
33
-
34
-	Sort(ports, func(ip, jp Port) bool {
35
-		return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp")
36
-	})
37
-
38
-	first := ports[0]
39
-	if fmt.Sprint(first) != "6379/tcp" {
40
-		t.Fail()
41
-	}
42
-}
43
-
44
-func TestSortPortMap(t *testing.T) {
45
-	ports := []Port{
46
-		Port("22/tcp"),
47
-		Port("22/udp"),
48
-		Port("8000/tcp"),
49
-		Port("6379/tcp"),
50
-		Port("9999/tcp"),
51
-	}
52
-
53
-	portMap := PortMap{
54
-		Port("22/tcp"): []PortBinding{
55
-			{},
56
-		},
57
-		Port("8000/tcp"): []PortBinding{
58
-			{},
59
-		},
60
-		Port("6379/tcp"): []PortBinding{
61
-			{},
62
-			{HostIP: "0.0.0.0", HostPort: "32749"},
63
-		},
64
-		Port("9999/tcp"): []PortBinding{
65
-			{HostIP: "0.0.0.0", HostPort: "40000"},
66
-		},
67
-	}
68
-
69
-	SortPortMap(ports, portMap)
70
-	if !reflect.DeepEqual(ports, []Port{
71
-		Port("9999/tcp"),
72
-		Port("6379/tcp"),
73
-		Port("8000/tcp"),
74
-		Port("22/tcp"),
75
-		Port("22/udp"),
76
-	}) {
77
-		t.Errorf("failed to prioritize port with explicit mappings, got %v", ports)
78
-	}
79
-	if pm := portMap[Port("6379/tcp")]; !reflect.DeepEqual(pm, []PortBinding{
80
-		{HostIP: "0.0.0.0", HostPort: "32749"},
81
-		{},
82
-	}) {
83
-		t.Errorf("failed to prioritize bindings with explicit mappings, got %v", pm)
84
-	}
85
-}
86 1
deleted file mode 100644
... ...
@@ -1,216 +0,0 @@
1
-package proxy
2
-
3
-import (
4
-	"bytes"
5
-	"fmt"
6
-	"io"
7
-	"net"
8
-	"strings"
9
-	"testing"
10
-	"time"
11
-)
12
-
13
-var testBuf = []byte("Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo")
14
-var testBufSize = len(testBuf)
15
-
16
-type EchoServer interface {
17
-	Run()
18
-	Close()
19
-	LocalAddr() net.Addr
20
-}
21
-
22
-type TCPEchoServer struct {
23
-	listener net.Listener
24
-	testCtx  *testing.T
25
-}
26
-
27
-type UDPEchoServer struct {
28
-	conn    net.PacketConn
29
-	testCtx *testing.T
30
-}
31
-
32
-func NewEchoServer(t *testing.T, proto, address string) EchoServer {
33
-	var server EchoServer
34
-	if strings.HasPrefix(proto, "tcp") {
35
-		listener, err := net.Listen(proto, address)
36
-		if err != nil {
37
-			t.Fatal(err)
38
-		}
39
-		server = &TCPEchoServer{listener: listener, testCtx: t}
40
-	} else {
41
-		socket, err := net.ListenPacket(proto, address)
42
-		if err != nil {
43
-			t.Fatal(err)
44
-		}
45
-		server = &UDPEchoServer{conn: socket, testCtx: t}
46
-	}
47
-	return server
48
-}
49
-
50
-func (server *TCPEchoServer) Run() {
51
-	go func() {
52
-		for {
53
-			client, err := server.listener.Accept()
54
-			if err != nil {
55
-				return
56
-			}
57
-			go func(client net.Conn) {
58
-				if _, err := io.Copy(client, client); err != nil {
59
-					server.testCtx.Logf("can't echo to the client: %v\n", err.Error())
60
-				}
61
-				client.Close()
62
-			}(client)
63
-		}
64
-	}()
65
-}
66
-
67
-func (server *TCPEchoServer) LocalAddr() net.Addr { return server.listener.Addr() }
68
-func (server *TCPEchoServer) Close()              { server.listener.Addr() }
69
-
70
-func (server *UDPEchoServer) Run() {
71
-	go func() {
72
-		readBuf := make([]byte, 1024)
73
-		for {
74
-			read, from, err := server.conn.ReadFrom(readBuf)
75
-			if err != nil {
76
-				return
77
-			}
78
-			for i := 0; i != read; {
79
-				written, err := server.conn.WriteTo(readBuf[i:read], from)
80
-				if err != nil {
81
-					break
82
-				}
83
-				i += written
84
-			}
85
-		}
86
-	}()
87
-}
88
-
89
-func (server *UDPEchoServer) LocalAddr() net.Addr { return server.conn.LocalAddr() }
90
-func (server *UDPEchoServer) Close()              { server.conn.Close() }
91
-
92
-func testProxyAt(t *testing.T, proto string, proxy Proxy, addr string) {
93
-	defer proxy.Close()
94
-	go proxy.Run()
95
-	client, err := net.Dial(proto, addr)
96
-	if err != nil {
97
-		t.Fatalf("Can't connect to the proxy: %v", err)
98
-	}
99
-	defer client.Close()
100
-	client.SetDeadline(time.Now().Add(10 * time.Second))
101
-	if _, err = client.Write(testBuf); err != nil {
102
-		t.Fatal(err)
103
-	}
104
-	recvBuf := make([]byte, testBufSize)
105
-	if _, err = client.Read(recvBuf); err != nil {
106
-		t.Fatal(err)
107
-	}
108
-	if !bytes.Equal(testBuf, recvBuf) {
109
-		t.Fatal(fmt.Errorf("Expected [%v] but got [%v]", testBuf, recvBuf))
110
-	}
111
-}
112
-
113
-func testProxy(t *testing.T, proto string, proxy Proxy) {
114
-	testProxyAt(t, proto, proxy, proxy.FrontendAddr().String())
115
-}
116
-
117
-func TestTCP4Proxy(t *testing.T) {
118
-	backend := NewEchoServer(t, "tcp", "127.0.0.1:0")
119
-	defer backend.Close()
120
-	backend.Run()
121
-	frontendAddr := &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0}
122
-	proxy, err := NewProxy(frontendAddr, backend.LocalAddr())
123
-	if err != nil {
124
-		t.Fatal(err)
125
-	}
126
-	testProxy(t, "tcp", proxy)
127
-}
128
-
129
-func TestTCP6Proxy(t *testing.T) {
130
-	backend := NewEchoServer(t, "tcp", "[::1]:0")
131
-	defer backend.Close()
132
-	backend.Run()
133
-	frontendAddr := &net.TCPAddr{IP: net.IPv6loopback, Port: 0}
134
-	proxy, err := NewProxy(frontendAddr, backend.LocalAddr())
135
-	if err != nil {
136
-		t.Fatal(err)
137
-	}
138
-	testProxy(t, "tcp", proxy)
139
-}
140
-
141
-func TestTCPDualStackProxy(t *testing.T) {
142
-	// If I understand `godoc -src net favoriteAddrFamily` (used by the
143
-	// net.Listen* functions) correctly this should work, but it doesn't.
144
-	t.Skip("No support for dual stack yet")
145
-	backend := NewEchoServer(t, "tcp", "[::1]:0")
146
-	defer backend.Close()
147
-	backend.Run()
148
-	frontendAddr := &net.TCPAddr{IP: net.IPv6loopback, Port: 0}
149
-	proxy, err := NewProxy(frontendAddr, backend.LocalAddr())
150
-	if err != nil {
151
-		t.Fatal(err)
152
-	}
153
-	ipv4ProxyAddr := &net.TCPAddr{
154
-		IP:   net.IPv4(127, 0, 0, 1),
155
-		Port: proxy.FrontendAddr().(*net.TCPAddr).Port,
156
-	}
157
-	testProxyAt(t, "tcp", proxy, ipv4ProxyAddr.String())
158
-}
159
-
160
-func TestUDP4Proxy(t *testing.T) {
161
-	backend := NewEchoServer(t, "udp", "127.0.0.1:0")
162
-	defer backend.Close()
163
-	backend.Run()
164
-	frontendAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0}
165
-	proxy, err := NewProxy(frontendAddr, backend.LocalAddr())
166
-	if err != nil {
167
-		t.Fatal(err)
168
-	}
169
-	testProxy(t, "udp", proxy)
170
-}
171
-
172
-func TestUDP6Proxy(t *testing.T) {
173
-	backend := NewEchoServer(t, "udp", "[::1]:0")
174
-	defer backend.Close()
175
-	backend.Run()
176
-	frontendAddr := &net.UDPAddr{IP: net.IPv6loopback, Port: 0}
177
-	proxy, err := NewProxy(frontendAddr, backend.LocalAddr())
178
-	if err != nil {
179
-		t.Fatal(err)
180
-	}
181
-	testProxy(t, "udp", proxy)
182
-}
183
-
184
-func TestUDPWriteError(t *testing.T) {
185
-	frontendAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0}
186
-	// Hopefully, this port will be free: */
187
-	backendAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 25587}
188
-	proxy, err := NewProxy(frontendAddr, backendAddr)
189
-	if err != nil {
190
-		t.Fatal(err)
191
-	}
192
-	defer proxy.Close()
193
-	go proxy.Run()
194
-	client, err := net.Dial("udp", "127.0.0.1:25587")
195
-	if err != nil {
196
-		t.Fatalf("Can't connect to the proxy: %v", err)
197
-	}
198
-	defer client.Close()
199
-	// Make sure the proxy doesn't stop when there is no actual backend:
200
-	client.Write(testBuf)
201
-	client.Write(testBuf)
202
-	backend := NewEchoServer(t, "udp", "127.0.0.1:25587")
203
-	defer backend.Close()
204
-	backend.Run()
205
-	client.SetDeadline(time.Now().Add(10 * time.Second))
206
-	if _, err = client.Write(testBuf); err != nil {
207
-		t.Fatal(err)
208
-	}
209
-	recvBuf := make([]byte, testBufSize)
210
-	if _, err = client.Read(recvBuf); err != nil {
211
-		t.Fatal(err)
212
-	}
213
-	if !bytes.Equal(testBuf, recvBuf) {
214
-		t.Fatal(fmt.Errorf("Expected [%v] but got [%v]", testBuf, recvBuf))
215
-	}
216
-}
217 1
deleted file mode 100644
... ...
@@ -1,36 +0,0 @@
1
-// Package proxy provides a network Proxy interface and implementations for TCP and UDP.
2
-package proxy
3
-
4
-import (
5
-	"fmt"
6
-	"net"
7
-)
8
-
9
-// Proxy defines the behavior of a proxy. It forwards traffic back and forth
10
-// between two endpoints : the frontend and the backend.
11
-// It can be used to do software port-mapping between two addresses.
12
-// e.g. forward all traffic between the frontend (host) 127.0.0.1:3000
13
-// to the backend (container) at 172.17.42.108:4000.
14
-type Proxy interface {
15
-	// Run starts forwarding traffic back and forth between the front
16
-	// and back-end addresses.
17
-	Run()
18
-	// Close stops forwarding traffic and close both ends of the Proxy.
19
-	Close()
20
-	// FrontendAddr returns the address on which the proxy is listening.
21
-	FrontendAddr() net.Addr
22
-	// BackendAddr returns the proxied address.
23
-	BackendAddr() net.Addr
24
-}
25
-
26
-// NewProxy creates a Proxy according to the specified frontendAddr and backendAddr.
27
-func NewProxy(frontendAddr, backendAddr net.Addr) (Proxy, error) {
28
-	switch frontendAddr.(type) {
29
-	case *net.UDPAddr:
30
-		return NewUDPProxy(frontendAddr.(*net.UDPAddr), backendAddr.(*net.UDPAddr))
31
-	case *net.TCPAddr:
32
-		return NewTCPProxy(frontendAddr.(*net.TCPAddr), backendAddr.(*net.TCPAddr))
33
-	default:
34
-		panic(fmt.Errorf("Unsupported protocol"))
35
-	}
36
-}
37 1
deleted file mode 100644
... ...
@@ -1,31 +0,0 @@
1
-package proxy
2
-
3
-import (
4
-	"net"
5
-)
6
-
7
-// StubProxy is a proxy that is a stub (does nothing).
8
-type StubProxy struct {
9
-	frontendAddr net.Addr
10
-	backendAddr  net.Addr
11
-}
12
-
13
-// Run does nothing.
14
-func (p *StubProxy) Run() {}
15
-
16
-// Close does nothing.
17
-func (p *StubProxy) Close() {}
18
-
19
-// FrontendAddr returns the frontend address.
20
-func (p *StubProxy) FrontendAddr() net.Addr { return p.frontendAddr }
21
-
22
-// BackendAddr returns the backend address.
23
-func (p *StubProxy) BackendAddr() net.Addr { return p.backendAddr }
24
-
25
-// NewStubProxy creates a new StubProxy
26
-func NewStubProxy(frontendAddr, backendAddr net.Addr) (Proxy, error) {
27
-	return &StubProxy{
28
-		frontendAddr: frontendAddr,
29
-		backendAddr:  backendAddr,
30
-	}, nil
31
-}
32 1
deleted file mode 100644
... ...
@@ -1,99 +0,0 @@
1
-package proxy
2
-
3
-import (
4
-	"io"
5
-	"net"
6
-	"syscall"
7
-
8
-	"github.com/Sirupsen/logrus"
9
-)
10
-
11
-// TCPProxy is a proxy for TCP connections. It implements the Proxy interface to
12
-// handle TCP traffic forwarding between the frontend and backend addresses.
13
-type TCPProxy struct {
14
-	listener     *net.TCPListener
15
-	frontendAddr *net.TCPAddr
16
-	backendAddr  *net.TCPAddr
17
-}
18
-
19
-// NewTCPProxy creates a new TCPProxy.
20
-func NewTCPProxy(frontendAddr, backendAddr *net.TCPAddr) (*TCPProxy, error) {
21
-	listener, err := net.ListenTCP("tcp", frontendAddr)
22
-	if err != nil {
23
-		return nil, err
24
-	}
25
-	// If the port in frontendAddr was 0 then ListenTCP will have a picked
26
-	// a port to listen on, hence the call to Addr to get that actual port:
27
-	return &TCPProxy{
28
-		listener:     listener,
29
-		frontendAddr: listener.Addr().(*net.TCPAddr),
30
-		backendAddr:  backendAddr,
31
-	}, nil
32
-}
33
-
34
-func (proxy *TCPProxy) clientLoop(client *net.TCPConn, quit chan bool) {
35
-	backend, err := net.DialTCP("tcp", nil, proxy.backendAddr)
36
-	if err != nil {
37
-		logrus.Printf("Can't forward traffic to backend tcp/%v: %s\n", proxy.backendAddr, err)
38
-		client.Close()
39
-		return
40
-	}
41
-
42
-	event := make(chan int64)
43
-	var broker = func(to, from *net.TCPConn) {
44
-		written, err := io.Copy(to, from)
45
-		if err != nil {
46
-			// If the socket we are writing to is shutdown with
47
-			// SHUT_WR, forward it to the other end of the pipe:
48
-			if err, ok := err.(*net.OpError); ok && err.Err == syscall.EPIPE {
49
-				from.CloseWrite()
50
-			}
51
-		}
52
-		to.CloseRead()
53
-		event <- written
54
-	}
55
-
56
-	go broker(client, backend)
57
-	go broker(backend, client)
58
-
59
-	var transferred int64
60
-	for i := 0; i < 2; i++ {
61
-		select {
62
-		case written := <-event:
63
-			transferred += written
64
-		case <-quit:
65
-			// Interrupt the two brokers and "join" them.
66
-			client.Close()
67
-			backend.Close()
68
-			for ; i < 2; i++ {
69
-				transferred += <-event
70
-			}
71
-			return
72
-		}
73
-	}
74
-	client.Close()
75
-	backend.Close()
76
-}
77
-
78
-// Run starts forwarding the traffic using TCP.
79
-func (proxy *TCPProxy) Run() {
80
-	quit := make(chan bool)
81
-	defer close(quit)
82
-	for {
83
-		client, err := proxy.listener.Accept()
84
-		if err != nil {
85
-			logrus.Printf("Stopping proxy on tcp/%v for tcp/%v (%s)", proxy.frontendAddr, proxy.backendAddr, err)
86
-			return
87
-		}
88
-		go proxy.clientLoop(client.(*net.TCPConn), quit)
89
-	}
90
-}
91
-
92
-// Close stops forwarding the traffic.
93
-func (proxy *TCPProxy) Close() { proxy.listener.Close() }
94
-
95
-// FrontendAddr returns the TCP address on which the proxy is listening.
96
-func (proxy *TCPProxy) FrontendAddr() net.Addr { return proxy.frontendAddr }
97
-
98
-// BackendAddr returns the TCP proxied address.
99
-func (proxy *TCPProxy) BackendAddr() net.Addr { return proxy.backendAddr }
100 1
deleted file mode 100644
... ...
@@ -1,169 +0,0 @@
1
-package proxy
2
-
3
-import (
4
-	"encoding/binary"
5
-	"net"
6
-	"strings"
7
-	"sync"
8
-	"syscall"
9
-	"time"
10
-
11
-	"github.com/Sirupsen/logrus"
12
-)
13
-
14
-const (
15
-	// UDPConnTrackTimeout is the timeout used for UDP connection tracking
16
-	UDPConnTrackTimeout = 90 * time.Second
17
-	// UDPBufSize is the buffer size for the UDP proxy
18
-	UDPBufSize = 65507
19
-)
20
-
21
-// A net.Addr where the IP is split into two fields so you can use it as a key
22
-// in a map:
23
-type connTrackKey struct {
24
-	IPHigh uint64
25
-	IPLow  uint64
26
-	Port   int
27
-}
28
-
29
-func newConnTrackKey(addr *net.UDPAddr) *connTrackKey {
30
-	if len(addr.IP) == net.IPv4len {
31
-		return &connTrackKey{
32
-			IPHigh: 0,
33
-			IPLow:  uint64(binary.BigEndian.Uint32(addr.IP)),
34
-			Port:   addr.Port,
35
-		}
36
-	}
37
-	return &connTrackKey{
38
-		IPHigh: binary.BigEndian.Uint64(addr.IP[:8]),
39
-		IPLow:  binary.BigEndian.Uint64(addr.IP[8:]),
40
-		Port:   addr.Port,
41
-	}
42
-}
43
-
44
-type connTrackMap map[connTrackKey]*net.UDPConn
45
-
46
-// UDPProxy is proxy for which handles UDP datagrams. It implements the Proxy
47
-// interface to handle UDP traffic forwarding between the frontend and backend
48
-// addresses.
49
-type UDPProxy struct {
50
-	listener       *net.UDPConn
51
-	frontendAddr   *net.UDPAddr
52
-	backendAddr    *net.UDPAddr
53
-	connTrackTable connTrackMap
54
-	connTrackLock  sync.Mutex
55
-}
56
-
57
-// NewUDPProxy creates a new UDPProxy.
58
-func NewUDPProxy(frontendAddr, backendAddr *net.UDPAddr) (*UDPProxy, error) {
59
-	listener, err := net.ListenUDP("udp", frontendAddr)
60
-	if err != nil {
61
-		return nil, err
62
-	}
63
-	return &UDPProxy{
64
-		listener:       listener,
65
-		frontendAddr:   listener.LocalAddr().(*net.UDPAddr),
66
-		backendAddr:    backendAddr,
67
-		connTrackTable: make(connTrackMap),
68
-	}, nil
69
-}
70
-
71
-func (proxy *UDPProxy) replyLoop(proxyConn *net.UDPConn, clientAddr *net.UDPAddr, clientKey *connTrackKey) {
72
-	defer func() {
73
-		proxy.connTrackLock.Lock()
74
-		delete(proxy.connTrackTable, *clientKey)
75
-		proxy.connTrackLock.Unlock()
76
-		proxyConn.Close()
77
-	}()
78
-
79
-	readBuf := make([]byte, UDPBufSize)
80
-	for {
81
-		proxyConn.SetReadDeadline(time.Now().Add(UDPConnTrackTimeout))
82
-	again:
83
-		read, err := proxyConn.Read(readBuf)
84
-		if err != nil {
85
-			if err, ok := err.(*net.OpError); ok && err.Err == syscall.ECONNREFUSED {
86
-				// This will happen if the last write failed
87
-				// (e.g: nothing is actually listening on the
88
-				// proxied port on the container), ignore it
89
-				// and continue until UDPConnTrackTimeout
90
-				// expires:
91
-				goto again
92
-			}
93
-			return
94
-		}
95
-		for i := 0; i != read; {
96
-			written, err := proxy.listener.WriteToUDP(readBuf[i:read], clientAddr)
97
-			if err != nil {
98
-				return
99
-			}
100
-			i += written
101
-		}
102
-	}
103
-}
104
-
105
-// Run starts forwarding the traffic using UDP.
106
-func (proxy *UDPProxy) Run() {
107
-	readBuf := make([]byte, UDPBufSize)
108
-	for {
109
-		read, from, err := proxy.listener.ReadFromUDP(readBuf)
110
-		if err != nil {
111
-			// NOTE: Apparently ReadFrom doesn't return
112
-			// ECONNREFUSED like Read do (see comment in
113
-			// UDPProxy.replyLoop)
114
-			if !isClosedError(err) {
115
-				logrus.Printf("Stopping proxy on udp/%v for udp/%v (%s)", proxy.frontendAddr, proxy.backendAddr, err)
116
-			}
117
-			break
118
-		}
119
-
120
-		fromKey := newConnTrackKey(from)
121
-		proxy.connTrackLock.Lock()
122
-		proxyConn, hit := proxy.connTrackTable[*fromKey]
123
-		if !hit {
124
-			proxyConn, err = net.DialUDP("udp", nil, proxy.backendAddr)
125
-			if err != nil {
126
-				logrus.Printf("Can't proxy a datagram to udp/%s: %s\n", proxy.backendAddr, err)
127
-				proxy.connTrackLock.Unlock()
128
-				continue
129
-			}
130
-			proxy.connTrackTable[*fromKey] = proxyConn
131
-			go proxy.replyLoop(proxyConn, from, fromKey)
132
-		}
133
-		proxy.connTrackLock.Unlock()
134
-		for i := 0; i != read; {
135
-			written, err := proxyConn.Write(readBuf[i:read])
136
-			if err != nil {
137
-				logrus.Printf("Can't proxy a datagram to udp/%s: %s\n", proxy.backendAddr, err)
138
-				break
139
-			}
140
-			i += written
141
-		}
142
-	}
143
-}
144
-
145
-// Close stops forwarding the traffic.
146
-func (proxy *UDPProxy) Close() {
147
-	proxy.listener.Close()
148
-	proxy.connTrackLock.Lock()
149
-	defer proxy.connTrackLock.Unlock()
150
-	for _, conn := range proxy.connTrackTable {
151
-		conn.Close()
152
-	}
153
-}
154
-
155
-// FrontendAddr returns the UDP address on which the proxy is listening.
156
-func (proxy *UDPProxy) FrontendAddr() net.Addr { return proxy.frontendAddr }
157
-
158
-// BackendAddr returns the proxied UDP address.
159
-func (proxy *UDPProxy) BackendAddr() net.Addr { return proxy.backendAddr }
160
-
161
-func isClosedError(err error) bool {
162
-	/* This comparison is ugly, but unfortunately, net.go doesn't export errClosing.
163
-	 * See:
164
-	 * http://golang.org/src/pkg/net/net.go
165
-	 * https://code.google.com/p/go/issues/detail?id=4337
166
-	 * https://groups.google.com/forum/#!msg/golang-nuts/0_aaCvBmOcM/SptmDyX1XJMJ
167
-	 */
168
-	return strings.HasSuffix(err.Error(), "use of closed network connection")
169
-}
... ...
@@ -1,3 +1,5 @@
1
+[![GoDoc](https://godoc.org/github.com/docker/go-units?status.svg)](https://godoc.org/github.com/docker/go-units)
2
+
1 3
 # Introduction
2 4
 
3 5
 go-units is a library to transform human friendly measurements into machine friendly values.
... ...
@@ -137,7 +137,7 @@ func (m *Manager) Apply(pid int) (err error) {
137 137
 	m.Paths = paths
138 138
 
139 139
 	if paths["cpu"] != "" {
140
-		if err := CheckCpushares(paths["cpu"], c.CpuShares); err != nil {
140
+		if err := CheckCpushares(paths["cpu"], c.Resources.CpuShares); err != nil {
141 141
 			return err
142 142
 		}
143 143
 	}
... ...
@@ -202,15 +202,15 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
202 202
 	if err != nil {
203 203
 		return err
204 204
 	}
205
-	prevState := m.Cgroups.Freezer
206
-	m.Cgroups.Freezer = state
205
+	prevState := m.Cgroups.Resources.Freezer
206
+	m.Cgroups.Resources.Freezer = state
207 207
 	freezer, err := subsystems.Get("freezer")
208 208
 	if err != nil {
209 209
 		return err
210 210
 	}
211 211
 	err = freezer.Set(dir, m.Cgroups)
212 212
 	if err != nil {
213
-		m.Cgroups.Freezer = prevState
213
+		m.Cgroups.Resources.Freezer = prevState
214 214
 		return err
215 215
 	}
216 216
 	return nil
... ...
@@ -35,18 +35,18 @@ func (s *BlkioGroup) Apply(d *cgroupData) error {
35 35
 }
36 36
 
37 37
 func (s *BlkioGroup) Set(path string, cgroup *configs.Cgroup) error {
38
-	if cgroup.BlkioWeight != 0 {
39
-		if err := writeFile(path, "blkio.weight", strconv.FormatUint(uint64(cgroup.BlkioWeight), 10)); err != nil {
38
+	if cgroup.Resources.BlkioWeight != 0 {
39
+		if err := writeFile(path, "blkio.weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioWeight), 10)); err != nil {
40 40
 			return err
41 41
 		}
42 42
 	}
43 43
 
44
-	if cgroup.BlkioLeafWeight != 0 {
45
-		if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(cgroup.BlkioLeafWeight), 10)); err != nil {
44
+	if cgroup.Resources.BlkioLeafWeight != 0 {
45
+		if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioLeafWeight), 10)); err != nil {
46 46
 			return err
47 47
 		}
48 48
 	}
49
-	for _, wd := range cgroup.BlkioWeightDevice {
49
+	for _, wd := range cgroup.Resources.BlkioWeightDevice {
50 50
 		if err := writeFile(path, "blkio.weight_device", wd.WeightString()); err != nil {
51 51
 			return err
52 52
 		}
... ...
@@ -54,22 +54,22 @@ func (s *BlkioGroup) Set(path string, cgroup *configs.Cgroup) error {
54 54
 			return err
55 55
 		}
56 56
 	}
57
-	for _, td := range cgroup.BlkioThrottleReadBpsDevice {
57
+	for _, td := range cgroup.Resources.BlkioThrottleReadBpsDevice {
58 58
 		if err := writeFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil {
59 59
 			return err
60 60
 		}
61 61
 	}
62
-	for _, td := range cgroup.BlkioThrottleWriteBpsDevice {
62
+	for _, td := range cgroup.Resources.BlkioThrottleWriteBpsDevice {
63 63
 		if err := writeFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil {
64 64
 			return err
65 65
 		}
66 66
 	}
67
-	for _, td := range cgroup.BlkioThrottleReadIOPSDevice {
67
+	for _, td := range cgroup.Resources.BlkioThrottleReadIOPSDevice {
68 68
 		if err := writeFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil {
69 69
 			return err
70 70
 		}
71 71
 	}
72
-	for _, td := range cgroup.BlkioThrottleWriteIOPSDevice {
72
+	for _, td := range cgroup.Resources.BlkioThrottleWriteIOPSDevice {
73 73
 		if err := writeFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil {
74 74
 			return err
75 75
 		}
... ...
@@ -35,28 +35,28 @@ func (s *CpuGroup) Apply(d *cgroupData) error {
35 35
 }
36 36
 
37 37
 func (s *CpuGroup) Set(path string, cgroup *configs.Cgroup) error {
38
-	if cgroup.CpuShares != 0 {
39
-		if err := writeFile(path, "cpu.shares", strconv.FormatInt(cgroup.CpuShares, 10)); err != nil {
38
+	if cgroup.Resources.CpuShares != 0 {
39
+		if err := writeFile(path, "cpu.shares", strconv.FormatInt(cgroup.Resources.CpuShares, 10)); err != nil {
40 40
 			return err
41 41
 		}
42 42
 	}
43
-	if cgroup.CpuPeriod != 0 {
44
-		if err := writeFile(path, "cpu.cfs_period_us", strconv.FormatInt(cgroup.CpuPeriod, 10)); err != nil {
43
+	if cgroup.Resources.CpuPeriod != 0 {
44
+		if err := writeFile(path, "cpu.cfs_period_us", strconv.FormatInt(cgroup.Resources.CpuPeriod, 10)); err != nil {
45 45
 			return err
46 46
 		}
47 47
 	}
48
-	if cgroup.CpuQuota != 0 {
49
-		if err := writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(cgroup.CpuQuota, 10)); err != nil {
48
+	if cgroup.Resources.CpuQuota != 0 {
49
+		if err := writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(cgroup.Resources.CpuQuota, 10)); err != nil {
50 50
 			return err
51 51
 		}
52 52
 	}
53
-	if cgroup.CpuRtPeriod != 0 {
54
-		if err := writeFile(path, "cpu.rt_period_us", strconv.FormatInt(cgroup.CpuRtPeriod, 10)); err != nil {
53
+	if cgroup.Resources.CpuRtPeriod != 0 {
54
+		if err := writeFile(path, "cpu.rt_period_us", strconv.FormatInt(cgroup.Resources.CpuRtPeriod, 10)); err != nil {
55 55
 			return err
56 56
 		}
57 57
 	}
58
-	if cgroup.CpuRtRuntime != 0 {
59
-		if err := writeFile(path, "cpu.rt_runtime_us", strconv.FormatInt(cgroup.CpuRtRuntime, 10)); err != nil {
58
+	if cgroup.Resources.CpuRtRuntime != 0 {
59
+		if err := writeFile(path, "cpu.rt_runtime_us", strconv.FormatInt(cgroup.Resources.CpuRtRuntime, 10)); err != nil {
60 60
 			return err
61 61
 		}
62 62
 	}
... ...
@@ -29,13 +29,13 @@ func (s *CpusetGroup) Apply(d *cgroupData) error {
29 29
 }
30 30
 
31 31
 func (s *CpusetGroup) Set(path string, cgroup *configs.Cgroup) error {
32
-	if cgroup.CpusetCpus != "" {
33
-		if err := writeFile(path, "cpuset.cpus", cgroup.CpusetCpus); err != nil {
32
+	if cgroup.Resources.CpusetCpus != "" {
33
+		if err := writeFile(path, "cpuset.cpus", cgroup.Resources.CpusetCpus); err != nil {
34 34
 			return err
35 35
 		}
36 36
 	}
37
-	if cgroup.CpusetMems != "" {
38
-		if err := writeFile(path, "cpuset.mems", cgroup.CpusetMems); err != nil {
37
+	if cgroup.Resources.CpusetMems != "" {
38
+		if err := writeFile(path, "cpuset.mems", cgroup.Resources.CpusetMems); err != nil {
39 39
 			return err
40 40
 		}
41 41
 	}
... ...
@@ -30,12 +30,12 @@ func (s *DevicesGroup) Apply(d *cgroupData) error {
30 30
 }
31 31
 
32 32
 func (s *DevicesGroup) Set(path string, cgroup *configs.Cgroup) error {
33
-	if !cgroup.AllowAllDevices {
33
+	if !cgroup.Resources.AllowAllDevices {
34 34
 		if err := writeFile(path, "devices.deny", "a"); err != nil {
35 35
 			return err
36 36
 		}
37 37
 
38
-		for _, dev := range cgroup.AllowedDevices {
38
+		for _, dev := range cgroup.Resources.AllowedDevices {
39 39
 			if err := writeFile(path, "devices.allow", dev.CgroupString()); err != nil {
40 40
 				return err
41 41
 			}
... ...
@@ -47,7 +47,7 @@ func (s *DevicesGroup) Set(path string, cgroup *configs.Cgroup) error {
47 47
 		return err
48 48
 	}
49 49
 
50
-	for _, dev := range cgroup.DeniedDevices {
50
+	for _, dev := range cgroup.Resources.DeniedDevices {
51 51
 		if err := writeFile(path, "devices.deny", dev.CgroupString()); err != nil {
52 52
 			return err
53 53
 		}
... ...
@@ -32,9 +32,9 @@ func (s *FreezerGroup) Apply(d *cgroupData) error {
32 32
 }
33 33
 
34 34
 func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error {
35
-	switch cgroup.Freezer {
35
+	switch cgroup.Resources.Freezer {
36 36
 	case configs.Frozen, configs.Thawed:
37
-		if err := writeFile(path, "freezer.state", string(cgroup.Freezer)); err != nil {
37
+		if err := writeFile(path, "freezer.state", string(cgroup.Resources.Freezer)); err != nil {
38 38
 			return err
39 39
 		}
40 40
 
... ...
@@ -43,7 +43,7 @@ func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error {
43 43
 			if err != nil {
44 44
 				return err
45 45
 			}
46
-			if strings.TrimSpace(state) == string(cgroup.Freezer) {
46
+			if strings.TrimSpace(state) == string(cgroup.Resources.Freezer) {
47 47
 				break
48 48
 			}
49 49
 			time.Sleep(1 * time.Millisecond)
... ...
@@ -51,7 +51,7 @@ func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error {
51 51
 	case configs.Undefined:
52 52
 		return nil
53 53
 	default:
54
-		return fmt.Errorf("Invalid argument '%s' to freezer.state", string(cgroup.Freezer))
54
+		return fmt.Errorf("Invalid argument '%s' to freezer.state", string(cgroup.Resources.Freezer))
55 55
 	}
56 56
 
57 57
 	return nil
... ...
@@ -32,7 +32,7 @@ func (s *HugetlbGroup) Apply(d *cgroupData) error {
32 32
 }
33 33
 
34 34
 func (s *HugetlbGroup) Set(path string, cgroup *configs.Cgroup) error {
35
-	for _, hugetlb := range cgroup.HugetlbLimit {
35
+	for _, hugetlb := range cgroup.Resources.HugetlbLimit {
36 36
 		if err := writeFile(path, strings.Join([]string{"hugetlb", hugetlb.Pagesize, "limit_in_bytes"}, "."), strconv.FormatUint(hugetlb.Limit, 10)); err != nil {
37 37
 			return err
38 38
 		}
... ...
@@ -55,40 +55,40 @@ func (s *MemoryGroup) Apply(d *cgroupData) (err error) {
55 55
 }
56 56
 
57 57
 func (s *MemoryGroup) Set(path string, cgroup *configs.Cgroup) error {
58
-	if cgroup.Memory != 0 {
59
-		if err := writeFile(path, "memory.limit_in_bytes", strconv.FormatInt(cgroup.Memory, 10)); err != nil {
58
+	if cgroup.Resources.Memory != 0 {
59
+		if err := writeFile(path, "memory.limit_in_bytes", strconv.FormatInt(cgroup.Resources.Memory, 10)); err != nil {
60 60
 			return err
61 61
 		}
62 62
 	}
63
-	if cgroup.MemoryReservation != 0 {
64
-		if err := writeFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(cgroup.MemoryReservation, 10)); err != nil {
63
+	if cgroup.Resources.MemoryReservation != 0 {
64
+		if err := writeFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(cgroup.Resources.MemoryReservation, 10)); err != nil {
65 65
 			return err
66 66
 		}
67 67
 	}
68
-	if cgroup.MemorySwap > 0 {
69
-		if err := writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(cgroup.MemorySwap, 10)); err != nil {
68
+	if cgroup.Resources.MemorySwap > 0 {
69
+		if err := writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(cgroup.Resources.MemorySwap, 10)); err != nil {
70 70
 			return err
71 71
 		}
72 72
 	}
73
-	if cgroup.KernelMemory > 0 {
74
-		if err := writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(cgroup.KernelMemory, 10)); err != nil {
73
+	if cgroup.Resources.KernelMemory > 0 {
74
+		if err := writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(cgroup.Resources.KernelMemory, 10)); err != nil {
75 75
 			return err
76 76
 		}
77 77
 	}
78 78
 
79
-	if cgroup.OomKillDisable {
79
+	if cgroup.Resources.OomKillDisable {
80 80
 		if err := writeFile(path, "memory.oom_control", "1"); err != nil {
81 81
 			return err
82 82
 		}
83 83
 	}
84
-	if cgroup.MemorySwappiness >= 0 && cgroup.MemorySwappiness <= 100 {
85
-		if err := writeFile(path, "memory.swappiness", strconv.FormatInt(cgroup.MemorySwappiness, 10)); err != nil {
84
+	if cgroup.Resources.MemorySwappiness >= 0 && cgroup.Resources.MemorySwappiness <= 100 {
85
+		if err := writeFile(path, "memory.swappiness", strconv.FormatInt(cgroup.Resources.MemorySwappiness, 10)); err != nil {
86 86
 			return err
87 87
 		}
88
-	} else if cgroup.MemorySwappiness == -1 {
88
+	} else if cgroup.Resources.MemorySwappiness == -1 {
89 89
 		return nil
90 90
 	} else {
91
-		return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", cgroup.MemorySwappiness)
91
+		return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", cgroup.Resources.MemorySwappiness)
92 92
 	}
93 93
 
94 94
 	return nil
... ...
@@ -139,12 +139,12 @@ func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error {
139 139
 }
140 140
 
141 141
 func memoryAssigned(cgroup *configs.Cgroup) bool {
142
-	return cgroup.Memory != 0 ||
143
-		cgroup.MemoryReservation != 0 ||
144
-		cgroup.MemorySwap > 0 ||
145
-		cgroup.KernelMemory > 0 ||
146
-		cgroup.OomKillDisable ||
147
-		cgroup.MemorySwappiness != -1
142
+	return cgroup.Resources.Memory != 0 ||
143
+		cgroup.Resources.MemoryReservation != 0 ||
144
+		cgroup.Resources.MemorySwap > 0 ||
145
+		cgroup.Resources.KernelMemory > 0 ||
146
+		cgroup.Resources.OomKillDisable ||
147
+		cgroup.Resources.MemorySwappiness != -1
148 148
 }
149 149
 
150 150
 func getMemoryData(path, name string) (cgroups.MemoryData, error) {
... ...
@@ -28,8 +28,8 @@ func (s *NetClsGroup) Apply(d *cgroupData) error {
28 28
 }
29 29
 
30 30
 func (s *NetClsGroup) Set(path string, cgroup *configs.Cgroup) error {
31
-	if cgroup.NetClsClassid != "" {
32
-		if err := writeFile(path, "net_cls.classid", cgroup.NetClsClassid); err != nil {
31
+	if cgroup.Resources.NetClsClassid != "" {
32
+		if err := writeFile(path, "net_cls.classid", cgroup.Resources.NetClsClassid); err != nil {
33 33
 			return err
34 34
 		}
35 35
 	}
... ...
@@ -28,7 +28,7 @@ func (s *NetPrioGroup) Apply(d *cgroupData) error {
28 28
 }
29 29
 
30 30
 func (s *NetPrioGroup) Set(path string, cgroup *configs.Cgroup) error {
31
-	for _, prioMap := range cgroup.NetPrioIfpriomap {
31
+	for _, prioMap := range cgroup.Resources.NetPrioIfpriomap {
32 32
 		if err := writeFile(path, "net_prio.ifpriomap", prioMap.CgroupString()); err != nil {
33 33
 			return err
34 34
 		}
... ...
@@ -189,26 +189,26 @@ func (m *Manager) Apply(pid int) error {
189 189
 			newProp("DefaultDependencies", false))
190 190
 	}
191 191
 
192
-	if c.Memory != 0 {
192
+	if c.Resources.Memory != 0 {
193 193
 		properties = append(properties,
194
-			newProp("MemoryLimit", uint64(c.Memory)))
194
+			newProp("MemoryLimit", uint64(c.Resources.Memory)))
195 195
 	}
196 196
 
197
-	if c.CpuShares != 0 {
197
+	if c.Resources.CpuShares != 0 {
198 198
 		properties = append(properties,
199
-			newProp("CPUShares", uint64(c.CpuShares)))
199
+			newProp("CPUShares", uint64(c.Resources.CpuShares)))
200 200
 	}
201 201
 
202
-	if c.BlkioWeight != 0 {
202
+	if c.Resources.BlkioWeight != 0 {
203 203
 		properties = append(properties,
204
-			newProp("BlockIOWeight", uint64(c.BlkioWeight)))
204
+			newProp("BlockIOWeight", uint64(c.Resources.BlkioWeight)))
205 205
 	}
206 206
 
207 207
 	// We need to set kernel memory before processes join cgroup because
208 208
 	// kmem.limit_in_bytes can only be set when the cgroup is empty.
209 209
 	// And swap memory limit needs to be set after memory limit, only
210 210
 	// memory limit is handled by systemd, so it's kind of ugly here.
211
-	if c.KernelMemory > 0 {
211
+	if c.Resources.KernelMemory > 0 {
212 212
 		if err := setKernelMemory(c); err != nil {
213 213
 			return err
214 214
 		}
... ...
@@ -279,7 +279,7 @@ func (m *Manager) Apply(pid int) error {
279 279
 	m.Paths = paths
280 280
 
281 281
 	if paths["cpu"] != "" {
282
-		if err := fs.CheckCpushares(paths["cpu"], c.CpuShares); err != nil {
282
+		if err := fs.CheckCpushares(paths["cpu"], c.Resources.CpuShares); err != nil {
283 283
 			return err
284 284
 		}
285 285
 	}
... ...
@@ -334,23 +334,23 @@ func joinCpu(c *configs.Cgroup, pid int) error {
334 334
 	if err != nil && !cgroups.IsNotFound(err) {
335 335
 		return err
336 336
 	}
337
-	if c.CpuQuota != 0 {
338
-		if err = writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(c.CpuQuota, 10)); err != nil {
337
+	if c.Resources.CpuQuota != 0 {
338
+		if err = writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(c.Resources.CpuQuota, 10)); err != nil {
339 339
 			return err
340 340
 		}
341 341
 	}
342
-	if c.CpuPeriod != 0 {
343
-		if err = writeFile(path, "cpu.cfs_period_us", strconv.FormatInt(c.CpuPeriod, 10)); err != nil {
342
+	if c.Resources.CpuPeriod != 0 {
343
+		if err = writeFile(path, "cpu.cfs_period_us", strconv.FormatInt(c.Resources.CpuPeriod, 10)); err != nil {
344 344
 			return err
345 345
 		}
346 346
 	}
347
-	if c.CpuRtPeriod != 0 {
348
-		if err = writeFile(path, "cpu.rt_period_us", strconv.FormatInt(c.CpuRtPeriod, 10)); err != nil {
347
+	if c.Resources.CpuRtPeriod != 0 {
348
+		if err = writeFile(path, "cpu.rt_period_us", strconv.FormatInt(c.Resources.CpuRtPeriod, 10)); err != nil {
349 349
 			return err
350 350
 		}
351 351
 	}
352
-	if c.CpuRtRuntime != 0 {
353
-		if err = writeFile(path, "cpu.rt_runtime_us", strconv.FormatInt(c.CpuRtRuntime, 10)); err != nil {
352
+	if c.Resources.CpuRtRuntime != 0 {
353
+		if err = writeFile(path, "cpu.rt_runtime_us", strconv.FormatInt(c.Resources.CpuRtRuntime, 10)); err != nil {
354 354
 			return err
355 355
 		}
356 356
 	}
... ...
@@ -418,15 +418,15 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
418 418
 	if err != nil {
419 419
 		return err
420 420
 	}
421
-	prevState := m.Cgroups.Freezer
422
-	m.Cgroups.Freezer = state
421
+	prevState := m.Cgroups.Resources.Freezer
422
+	m.Cgroups.Resources.Freezer = state
423 423
 	freezer, err := subsystems.Get("freezer")
424 424
 	if err != nil {
425 425
 		return err
426 426
 	}
427 427
 	err = freezer.Set(path, m.Cgroups)
428 428
 	if err != nil {
429
-		m.Cgroups.Freezer = prevState
429
+		m.Cgroups.Resources.Freezer = prevState
430 430
 		return err
431 431
 	}
432 432
 	return nil
... ...
@@ -510,8 +510,8 @@ func setKernelMemory(c *configs.Cgroup) error {
510 510
 		return err
511 511
 	}
512 512
 
513
-	if c.KernelMemory > 0 {
514
-		err = writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(c.KernelMemory, 10))
513
+	if c.Resources.KernelMemory > 0 {
514
+		err = writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(c.Resources.KernelMemory, 10))
515 515
 		if err != nil {
516 516
 			return err
517 517
 		}
... ...
@@ -527,33 +527,33 @@ func joinMemory(c *configs.Cgroup, pid int) error {
527 527
 	}
528 528
 
529 529
 	// -1 disables memoryswap
530
-	if c.MemorySwap > 0 {
531
-		err = writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(c.MemorySwap, 10))
530
+	if c.Resources.MemorySwap > 0 {
531
+		err = writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(c.Resources.MemorySwap, 10))
532 532
 		if err != nil {
533 533
 			return err
534 534
 		}
535 535
 	}
536
-	if c.MemoryReservation > 0 {
537
-		err = writeFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(c.MemoryReservation, 10))
536
+	if c.Resources.MemoryReservation > 0 {
537
+		err = writeFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(c.Resources.MemoryReservation, 10))
538 538
 		if err != nil {
539 539
 			return err
540 540
 		}
541 541
 	}
542
-	if c.OomKillDisable {
542
+	if c.Resources.OomKillDisable {
543 543
 		if err := writeFile(path, "memory.oom_control", "1"); err != nil {
544 544
 			return err
545 545
 		}
546 546
 	}
547 547
 
548
-	if c.MemorySwappiness >= 0 && c.MemorySwappiness <= 100 {
549
-		err = writeFile(path, "memory.swappiness", strconv.FormatInt(c.MemorySwappiness, 10))
548
+	if c.Resources.MemorySwappiness >= 0 && c.Resources.MemorySwappiness <= 100 {
549
+		err = writeFile(path, "memory.swappiness", strconv.FormatInt(c.Resources.MemorySwappiness, 10))
550 550
 		if err != nil {
551 551
 			return err
552 552
 		}
553
-	} else if c.MemorySwappiness == -1 {
553
+	} else if c.Resources.MemorySwappiness == -1 {
554 554
 		return nil
555 555
 	} else {
556
-		return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", c.MemorySwappiness)
556
+		return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", c.Resources.MemorySwappiness)
557 557
 	}
558 558
 
559 559
 	return nil
... ...
@@ -582,12 +582,12 @@ func joinBlkio(c *configs.Cgroup, pid int) error {
582 582
 		return err
583 583
 	}
584 584
 	// systemd doesn't directly support this in the dbus properties
585
-	if c.BlkioLeafWeight != 0 {
586
-		if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(c.BlkioLeafWeight), 10)); err != nil {
585
+	if c.Resources.BlkioLeafWeight != 0 {
586
+		if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(c.Resources.BlkioLeafWeight), 10)); err != nil {
587 587
 			return err
588 588
 		}
589 589
 	}
590
-	for _, wd := range c.BlkioWeightDevice {
590
+	for _, wd := range c.Resources.BlkioWeightDevice {
591 591
 		if err := writeFile(path, "blkio.weight_device", wd.WeightString()); err != nil {
592 592
 			return err
593 593
 		}
... ...
@@ -595,22 +595,22 @@ func joinBlkio(c *configs.Cgroup, pid int) error {
595 595
 			return err
596 596
 		}
597 597
 	}
598
-	for _, td := range c.BlkioThrottleReadBpsDevice {
598
+	for _, td := range c.Resources.BlkioThrottleReadBpsDevice {
599 599
 		if err := writeFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil {
600 600
 			return err
601 601
 		}
602 602
 	}
603
-	for _, td := range c.BlkioThrottleWriteBpsDevice {
603
+	for _, td := range c.Resources.BlkioThrottleWriteBpsDevice {
604 604
 		if err := writeFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil {
605 605
 			return err
606 606
 		}
607 607
 	}
608
-	for _, td := range c.BlkioThrottleReadIOPSDevice {
608
+	for _, td := range c.Resources.BlkioThrottleReadIOPSDevice {
609 609
 		if err := writeFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil {
610 610
 			return err
611 611
 		}
612 612
 	}
613
-	for _, td := range c.BlkioThrottleWriteIOPSDevice {
613
+	for _, td := range c.Resources.BlkioThrottleWriteIOPSDevice {
614 614
 		if err := writeFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil {
615 615
 			return err
616 616
 		}
... ...
@@ -16,6 +16,14 @@ type Cgroup struct {
16 16
 	// name of parent cgroup or slice
17 17
 	Parent string `json:"parent"`
18 18
 
19
+	// ScopePrefix decribes prefix for the scope name
20
+	ScopePrefix string `json:"scope_prefix"`
21
+
22
+	// Resources contains various cgroups settings to apply
23
+	Resources *Resources `json:"resources"`
24
+}
25
+
26
+type Resources struct {
19 27
 	// If this is true allow access to any kind of device within the container.  If false, allow access only to devices explicitly listed in the allowed_devices list.
20 28
 	AllowAllDevices bool `json:"allow_all_devices"`
21 29
 
... ...
@@ -83,9 +91,6 @@ type Cgroup struct {
83 83
 	// Hugetlb limit (in bytes)
84 84
 	HugetlbLimit []*HugepageLimit `json:"hugetlb_limit"`
85 85
 
86
-	// ScopePrefix decribes prefix for the scope name
87
-	ScopePrefix string `json:"scope_prefix"`
88
-
89 86
 	// Whether to disable OOM Killer
90 87
 	OomKillDisable bool `json:"oom_kill_disable"`
91 88
 
... ...
@@ -985,7 +985,7 @@ func (c *linuxContainer) currentStatus() (Status, error) {
985 985
 		}
986 986
 		return 0, newSystemError(err)
987 987
 	}
988
-	if c.config.Cgroups != nil && c.config.Cgroups.Freezer == configs.Frozen {
988
+	if c.config.Cgroups != nil && c.config.Cgroups.Resources != nil && c.config.Cgroups.Resources.Freezer == configs.Frozen {
989 989
 		return Paused, nil
990 990
 	}
991 991
 	return Running, nil
... ...
@@ -14,6 +14,8 @@ const (
14 14
 	InitMsg         uint16 = 62000
15 15
 	PidAttr         uint16 = 27281
16 16
 	ConsolePathAttr uint16 = 27282
17
+	// When syscall.NLA_HDRLEN is in gccgo, take this out.
18
+	syscall_NLA_HDRLEN = (syscall.SizeofNlAttr + syscall.NLA_ALIGNTO - 1) & ^(syscall.NLA_ALIGNTO - 1)
17 19
 )
18 20
 
19 21
 type Int32msg struct {
... ...
@@ -34,7 +36,7 @@ func (msg *Int32msg) Serialize() []byte {
34 34
 }
35 35
 
36 36
 func (msg *Int32msg) Len() int {
37
-	return syscall.NLA_HDRLEN + 4
37
+	return syscall_NLA_HDRLEN + 4
38 38
 }
39 39
 
40 40
 // bytemsg has the following representation
... ...
@@ -56,5 +58,5 @@ func (msg *Bytemsg) Serialize() []byte {
56 56
 }
57 57
 
58 58
 func (msg *Bytemsg) Len() int {
59
-	return syscall.NLA_HDRLEN + len(msg.Value) + 1 // null-terminated
59
+	return syscall_NLA_HDRLEN + len(msg.Value) + 1 // null-terminated
60 60
 }