Browse code

Windows: Start refactor execdriver/driver.go

Signed-off-by: John Howard <jhoward@microsoft.com>

John Howard authored on 2015/04/28 06:27:00
Showing 2 changed files
... ...
@@ -1,21 +1,14 @@
1 1
 package execdriver
2 2
 
3 3
 import (
4
-	"encoding/json"
5 4
 	"errors"
6 5
 	"io"
7
-	"io/ioutil"
8
-	"os"
9 6
 	"os/exec"
10
-	"path/filepath"
11
-	"strconv"
12
-	"strings"
13 7
 	"time"
14 8
 
15
-	"github.com/docker/docker/daemon/execdriver/native/template"
9
+	// TODO Windows: Factor out ulimit
16 10
 	"github.com/docker/docker/pkg/ulimit"
17 11
 	"github.com/docker/libcontainer"
18
-	"github.com/docker/libcontainer/cgroups/fs"
19 12
 	"github.com/docker/libcontainer/configs"
20 13
 )
21 14
 
... ...
@@ -105,6 +98,7 @@ type NetworkInterface struct {
105 105
 	IPv6Gateway          string `json:"ipv6_gateway"`
106 106
 }
107 107
 
108
+// TODO Windows: Factor out ulimit.Rlimit
108 109
 type Resources struct {
109 110
 	Memory     int64            `json:"memory"`
110 111
 	MemorySwap int64            `json:"memory_swap"`
... ...
@@ -143,6 +137,9 @@ type ProcessConfig struct {
143 143
 	Console    string   `json:"-"` // dev/console path
144 144
 }
145 145
 
146
+// TODO Windows: Factor out unused fields such as LxcConfig, AppArmorProfile,
147
+// and CgroupParent.
148
+//
146 149
 // Process wrapps an os/exec.Cmd to add more metadata
147 150
 type Command struct {
148 151
 	ID                 string            `json:"id"`
... ...
@@ -168,143 +165,3 @@ type Command struct {
168 168
 	AppArmorProfile    string            `json:"apparmor_profile"`
169 169
 	CgroupParent       string            `json:"cgroup_parent"` // The parent cgroup for this command.
170 170
 }
171
-
172
-func InitContainer(c *Command) *configs.Config {
173
-	container := template.New()
174
-
175
-	container.Hostname = getEnv("HOSTNAME", c.ProcessConfig.Env)
176
-	container.Cgroups.Name = c.ID
177
-	container.Cgroups.AllowedDevices = c.AllowedDevices
178
-	container.Devices = c.AutoCreatedDevices
179
-	container.Rootfs = c.Rootfs
180
-	container.Readonlyfs = c.ReadonlyRootfs
181
-
182
-	// check to see if we are running in ramdisk to disable pivot root
183
-	container.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
184
-
185
-	// Default parent cgroup is "docker". Override if required.
186
-	if c.CgroupParent != "" {
187
-		container.Cgroups.Parent = c.CgroupParent
188
-	}
189
-	return container
190
-}
191
-
192
-func getEnv(key string, env []string) string {
193
-	for _, pair := range env {
194
-		parts := strings.Split(pair, "=")
195
-		if parts[0] == key {
196
-			return parts[1]
197
-		}
198
-	}
199
-	return ""
200
-}
201
-
202
-func SetupCgroups(container *configs.Config, c *Command) error {
203
-	if c.Resources != nil {
204
-		container.Cgroups.CpuShares = c.Resources.CpuShares
205
-		container.Cgroups.Memory = c.Resources.Memory
206
-		container.Cgroups.MemoryReservation = c.Resources.Memory
207
-		container.Cgroups.MemorySwap = c.Resources.MemorySwap
208
-		container.Cgroups.CpusetCpus = c.Resources.CpusetCpus
209
-		container.Cgroups.CpusetMems = c.Resources.CpusetMems
210
-		container.Cgroups.CpuQuota = c.Resources.CpuQuota
211
-	}
212
-
213
-	return nil
214
-}
215
-
216
-// Returns the network statistics for the network interfaces represented by the NetworkRuntimeInfo.
217
-func getNetworkInterfaceStats(interfaceName string) (*libcontainer.NetworkInterface, error) {
218
-	out := &libcontainer.NetworkInterface{Name: interfaceName}
219
-	// This can happen if the network runtime information is missing - possible if the
220
-	// container was created by an old version of libcontainer.
221
-	if interfaceName == "" {
222
-		return out, nil
223
-	}
224
-	type netStatsPair struct {
225
-		// Where to write the output.
226
-		Out *uint64
227
-		// The network stats file to read.
228
-		File string
229
-	}
230
-	// Ingress for host veth is from the container. Hence tx_bytes stat on the host veth is actually number of bytes received by the container.
231
-	netStats := []netStatsPair{
232
-		{Out: &out.RxBytes, File: "tx_bytes"},
233
-		{Out: &out.RxPackets, File: "tx_packets"},
234
-		{Out: &out.RxErrors, File: "tx_errors"},
235
-		{Out: &out.RxDropped, File: "tx_dropped"},
236
-
237
-		{Out: &out.TxBytes, File: "rx_bytes"},
238
-		{Out: &out.TxPackets, File: "rx_packets"},
239
-		{Out: &out.TxErrors, File: "rx_errors"},
240
-		{Out: &out.TxDropped, File: "rx_dropped"},
241
-	}
242
-	for _, netStat := range netStats {
243
-		data, err := readSysfsNetworkStats(interfaceName, netStat.File)
244
-		if err != nil {
245
-			return nil, err
246
-		}
247
-		*(netStat.Out) = data
248
-	}
249
-	return out, nil
250
-}
251
-
252
-// Reads the specified statistics available under /sys/class/net/<EthInterface>/statistics
253
-func readSysfsNetworkStats(ethInterface, statsFile string) (uint64, error) {
254
-	data, err := ioutil.ReadFile(filepath.Join("/sys/class/net", ethInterface, "statistics", statsFile))
255
-	if err != nil {
256
-		return 0, err
257
-	}
258
-	return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)
259
-}
260
-
261
-func Stats(containerDir string, containerMemoryLimit int64, machineMemory int64) (*ResourceStats, error) {
262
-	f, err := os.Open(filepath.Join(containerDir, "state.json"))
263
-	if err != nil {
264
-		return nil, err
265
-	}
266
-	defer f.Close()
267
-
268
-	type network struct {
269
-		Type              string
270
-		HostInterfaceName string
271
-	}
272
-
273
-	state := struct {
274
-		CgroupPaths map[string]string `json:"cgroup_paths"`
275
-		Networks    []network
276
-	}{}
277
-
278
-	if err := json.NewDecoder(f).Decode(&state); err != nil {
279
-		return nil, err
280
-	}
281
-	now := time.Now()
282
-
283
-	mgr := fs.Manager{Paths: state.CgroupPaths}
284
-	cstats, err := mgr.GetStats()
285
-	if err != nil {
286
-		return nil, err
287
-	}
288
-	stats := &libcontainer.Stats{CgroupStats: cstats}
289
-	// if the container does not have any memory limit specified set the
290
-	// limit to the machines memory
291
-	memoryLimit := containerMemoryLimit
292
-	if memoryLimit == 0 {
293
-		memoryLimit = machineMemory
294
-	}
295
-	for _, iface := range state.Networks {
296
-		switch iface.Type {
297
-		case "veth":
298
-			istats, err := getNetworkInterfaceStats(iface.HostInterfaceName)
299
-			if err != nil {
300
-				return nil, err
301
-			}
302
-			stats.Interfaces = append(stats.Interfaces, istats)
303
-		}
304
-	}
305
-	return &ResourceStats{
306
-		Stats:       stats,
307
-		Read:        now,
308
-		MemoryLimit: memoryLimit,
309
-	}, nil
310
-}
311 171
new file mode 100644
... ...
@@ -0,0 +1,156 @@
0
+package execdriver
1
+
2
+import (
3
+	"encoding/json"
4
+	"io/ioutil"
5
+	"os"
6
+	"path/filepath"
7
+	"strconv"
8
+	"strings"
9
+	"time"
10
+
11
+	"github.com/docker/docker/daemon/execdriver/native/template"
12
+	"github.com/docker/libcontainer"
13
+	"github.com/docker/libcontainer/cgroups/fs"
14
+	"github.com/docker/libcontainer/configs"
15
+)
16
+
17
+func InitContainer(c *Command) *configs.Config {
18
+	container := template.New()
19
+
20
+	container.Hostname = getEnv("HOSTNAME", c.ProcessConfig.Env)
21
+	container.Cgroups.Name = c.ID
22
+	container.Cgroups.AllowedDevices = c.AllowedDevices
23
+	container.Devices = c.AutoCreatedDevices
24
+	container.Rootfs = c.Rootfs
25
+	container.Readonlyfs = c.ReadonlyRootfs
26
+
27
+	// check to see if we are running in ramdisk to disable pivot root
28
+	container.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
29
+
30
+	// Default parent cgroup is "docker". Override if required.
31
+	if c.CgroupParent != "" {
32
+		container.Cgroups.Parent = c.CgroupParent
33
+	}
34
+	return container
35
+}
36
+
37
+func getEnv(key string, env []string) string {
38
+	for _, pair := range env {
39
+		parts := strings.Split(pair, "=")
40
+		if parts[0] == key {
41
+			return parts[1]
42
+		}
43
+	}
44
+	return ""
45
+}
46
+
47
+func SetupCgroups(container *configs.Config, c *Command) error {
48
+	if c.Resources != nil {
49
+		container.Cgroups.CpuShares = c.Resources.CpuShares
50
+		container.Cgroups.Memory = c.Resources.Memory
51
+		container.Cgroups.MemoryReservation = c.Resources.Memory
52
+		container.Cgroups.MemorySwap = c.Resources.MemorySwap
53
+		container.Cgroups.CpusetCpus = c.Resources.CpusetCpus
54
+		container.Cgroups.CpusetMems = c.Resources.CpusetMems
55
+		container.Cgroups.CpuQuota = c.Resources.CpuQuota
56
+	}
57
+
58
+	return nil
59
+}
60
+
61
+// Returns the network statistics for the network interfaces represented by the NetworkRuntimeInfo.
62
+func getNetworkInterfaceStats(interfaceName string) (*libcontainer.NetworkInterface, error) {
63
+	out := &libcontainer.NetworkInterface{Name: interfaceName}
64
+	// This can happen if the network runtime information is missing - possible if the
65
+	// container was created by an old version of libcontainer.
66
+	if interfaceName == "" {
67
+		return out, nil
68
+	}
69
+	type netStatsPair struct {
70
+		// Where to write the output.
71
+		Out *uint64
72
+		// The network stats file to read.
73
+		File string
74
+	}
75
+	// Ingress for host veth is from the container. Hence tx_bytes stat on the host veth is actually number of bytes received by the container.
76
+	netStats := []netStatsPair{
77
+		{Out: &out.RxBytes, File: "tx_bytes"},
78
+		{Out: &out.RxPackets, File: "tx_packets"},
79
+		{Out: &out.RxErrors, File: "tx_errors"},
80
+		{Out: &out.RxDropped, File: "tx_dropped"},
81
+
82
+		{Out: &out.TxBytes, File: "rx_bytes"},
83
+		{Out: &out.TxPackets, File: "rx_packets"},
84
+		{Out: &out.TxErrors, File: "rx_errors"},
85
+		{Out: &out.TxDropped, File: "rx_dropped"},
86
+	}
87
+	for _, netStat := range netStats {
88
+		data, err := readSysfsNetworkStats(interfaceName, netStat.File)
89
+		if err != nil {
90
+			return nil, err
91
+		}
92
+		*(netStat.Out) = data
93
+	}
94
+	return out, nil
95
+}
96
+
97
+// Reads the specified statistics available under /sys/class/net/<EthInterface>/statistics
98
+func readSysfsNetworkStats(ethInterface, statsFile string) (uint64, error) {
99
+	data, err := ioutil.ReadFile(filepath.Join("/sys/class/net", ethInterface, "statistics", statsFile))
100
+	if err != nil {
101
+		return 0, err
102
+	}
103
+	return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)
104
+}
105
+
106
+func Stats(containerDir string, containerMemoryLimit int64, machineMemory int64) (*ResourceStats, error) {
107
+	f, err := os.Open(filepath.Join(containerDir, "state.json"))
108
+	if err != nil {
109
+		return nil, err
110
+	}
111
+	defer f.Close()
112
+
113
+	type network struct {
114
+		Type              string
115
+		HostInterfaceName string
116
+	}
117
+
118
+	state := struct {
119
+		CgroupPaths map[string]string `json:"cgroup_paths"`
120
+		Networks    []network
121
+	}{}
122
+
123
+	if err := json.NewDecoder(f).Decode(&state); err != nil {
124
+		return nil, err
125
+	}
126
+	now := time.Now()
127
+
128
+	mgr := fs.Manager{Paths: state.CgroupPaths}
129
+	cstats, err := mgr.GetStats()
130
+	if err != nil {
131
+		return nil, err
132
+	}
133
+	stats := &libcontainer.Stats{CgroupStats: cstats}
134
+	// if the container does not have any memory limit specified set the
135
+	// limit to the machines memory
136
+	memoryLimit := containerMemoryLimit
137
+	if memoryLimit == 0 {
138
+		memoryLimit = machineMemory
139
+	}
140
+	for _, iface := range state.Networks {
141
+		switch iface.Type {
142
+		case "veth":
143
+			istats, err := getNetworkInterfaceStats(iface.HostInterfaceName)
144
+			if err != nil {
145
+				return nil, err
146
+			}
147
+			stats.Interfaces = append(stats.Interfaces, istats)
148
+		}
149
+	}
150
+	return &ResourceStats{
151
+		Stats:       stats,
152
+		Read:        now,
153
+		MemoryLimit: memoryLimit,
154
+	}, nil
155
+}