Browse code

Merge pull request #20938 from runcom/split-daemon

integration-cli: move daemon stuff to its own file

Sebastiaan van Stijn authored on 2016/03/04 23:09:35
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,457 @@
0
+package main
1
+
2
+import (
3
+	"encoding/json"
4
+	"errors"
5
+	"fmt"
6
+	"io"
7
+	"net/http"
8
+	"os"
9
+	"os/exec"
10
+	"path/filepath"
11
+	"strconv"
12
+	"strings"
13
+	"time"
14
+
15
+	"github.com/docker/docker/opts"
16
+	"github.com/docker/docker/pkg/integration/checker"
17
+	"github.com/docker/docker/pkg/ioutils"
18
+	"github.com/docker/docker/pkg/tlsconfig"
19
+	"github.com/docker/go-connections/sockets"
20
+	"github.com/go-check/check"
21
+)
22
+
23
+// Daemon represents a Docker daemon for the testing framework.
24
+type Daemon struct {
25
+	// Defaults to "daemon"
26
+	// Useful to set to --daemon or -d for checking backwards compatibility
27
+	Command     string
28
+	GlobalFlags []string
29
+
30
+	id                string
31
+	c                 *check.C
32
+	logFile           *os.File
33
+	folder            string
34
+	root              string
35
+	stdin             io.WriteCloser
36
+	stdout, stderr    io.ReadCloser
37
+	cmd               *exec.Cmd
38
+	storageDriver     string
39
+	wait              chan error
40
+	userlandProxy     bool
41
+	useDefaultHost    bool
42
+	useDefaultTLSHost bool
43
+}
44
+
45
+type clientConfig struct {
46
+	transport *http.Transport
47
+	scheme    string
48
+	addr      string
49
+}
50
+
51
+// NewDaemon returns a Daemon instance to be used for testing.
52
+// This will create a directory such as d123456789 in the folder specified by $DEST.
53
+// The daemon will not automatically start.
54
+func NewDaemon(c *check.C) *Daemon {
55
+	dest := os.Getenv("DEST")
56
+	c.Assert(dest, check.Not(check.Equals), "", check.Commentf("Please set the DEST environment variable"))
57
+
58
+	id := fmt.Sprintf("d%d", time.Now().UnixNano()%100000000)
59
+	dir := filepath.Join(dest, id)
60
+	daemonFolder, err := filepath.Abs(dir)
61
+	c.Assert(err, check.IsNil, check.Commentf("Could not make %q an absolute path", dir))
62
+	daemonRoot := filepath.Join(daemonFolder, "root")
63
+
64
+	c.Assert(os.MkdirAll(daemonRoot, 0755), check.IsNil, check.Commentf("Could not create daemon root %q", dir))
65
+
66
+	userlandProxy := true
67
+	if env := os.Getenv("DOCKER_USERLANDPROXY"); env != "" {
68
+		if val, err := strconv.ParseBool(env); err != nil {
69
+			userlandProxy = val
70
+		}
71
+	}
72
+
73
+	return &Daemon{
74
+		Command:       "daemon",
75
+		id:            id,
76
+		c:             c,
77
+		folder:        daemonFolder,
78
+		root:          daemonRoot,
79
+		storageDriver: os.Getenv("DOCKER_GRAPHDRIVER"),
80
+		userlandProxy: userlandProxy,
81
+	}
82
+}
83
+
84
+func (d *Daemon) getClientConfig() (*clientConfig, error) {
85
+	var (
86
+		transport *http.Transport
87
+		scheme    string
88
+		addr      string
89
+		proto     string
90
+	)
91
+	if d.useDefaultTLSHost {
92
+		option := &tlsconfig.Options{
93
+			CAFile:   "fixtures/https/ca.pem",
94
+			CertFile: "fixtures/https/client-cert.pem",
95
+			KeyFile:  "fixtures/https/client-key.pem",
96
+		}
97
+		tlsConfig, err := tlsconfig.Client(*option)
98
+		if err != nil {
99
+			return nil, err
100
+		}
101
+		transport = &http.Transport{
102
+			TLSClientConfig: tlsConfig,
103
+		}
104
+		addr = fmt.Sprintf("%s:%d", opts.DefaultHTTPHost, opts.DefaultTLSHTTPPort)
105
+		scheme = "https"
106
+		proto = "tcp"
107
+	} else if d.useDefaultHost {
108
+		addr = opts.DefaultUnixSocket
109
+		proto = "unix"
110
+		scheme = "http"
111
+		transport = &http.Transport{}
112
+	} else {
113
+		addr = filepath.Join(d.folder, "docker.sock")
114
+		proto = "unix"
115
+		scheme = "http"
116
+		transport = &http.Transport{}
117
+	}
118
+
119
+	d.c.Assert(sockets.ConfigureTransport(transport, proto, addr), check.IsNil)
120
+
121
+	return &clientConfig{
122
+		transport: transport,
123
+		scheme:    scheme,
124
+		addr:      addr,
125
+	}, nil
126
+}
127
+
128
+// Start will start the daemon and return once it is ready to receive requests.
129
+// You can specify additional daemon flags.
130
+func (d *Daemon) Start(args ...string) error {
131
+	logFile, err := os.OpenFile(filepath.Join(d.folder, "docker.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
132
+	d.c.Assert(err, check.IsNil, check.Commentf("[%s] Could not create %s/docker.log", d.id, d.folder))
133
+
134
+	return d.StartWithLogFile(logFile, args...)
135
+}
136
+
137
+// StartWithLogFile will start the daemon and attach its streams to a given file.
138
+func (d *Daemon) StartWithLogFile(out *os.File, providedArgs ...string) error {
139
+	dockerBinary, err := exec.LookPath(dockerBinary)
140
+	d.c.Assert(err, check.IsNil, check.Commentf("[%s] could not find docker binary in $PATH", d.id))
141
+
142
+	args := append(d.GlobalFlags,
143
+		d.Command,
144
+		"--graph", d.root,
145
+		"--pidfile", fmt.Sprintf("%s/docker.pid", d.folder),
146
+		fmt.Sprintf("--userland-proxy=%t", d.userlandProxy),
147
+	)
148
+	if !(d.useDefaultHost || d.useDefaultTLSHost) {
149
+		args = append(args, []string{"--host", d.sock()}...)
150
+	}
151
+	if root := os.Getenv("DOCKER_REMAP_ROOT"); root != "" {
152
+		args = append(args, []string{"--userns-remap", root}...)
153
+	}
154
+
155
+	// If we don't explicitly set the log-level or debug flag(-D) then
156
+	// turn on debug mode
157
+	foundLog := false
158
+	foundSd := false
159
+	for _, a := range providedArgs {
160
+		if strings.Contains(a, "--log-level") || strings.Contains(a, "-D") || strings.Contains(a, "--debug") {
161
+			foundLog = true
162
+		}
163
+		if strings.Contains(a, "--storage-driver") {
164
+			foundSd = true
165
+		}
166
+	}
167
+	if !foundLog {
168
+		args = append(args, "--debug")
169
+	}
170
+	if d.storageDriver != "" && !foundSd {
171
+		args = append(args, "--storage-driver", d.storageDriver)
172
+	}
173
+
174
+	args = append(args, providedArgs...)
175
+	d.cmd = exec.Command(dockerBinary, args...)
176
+
177
+	d.cmd.Stdout = out
178
+	d.cmd.Stderr = out
179
+	d.logFile = out
180
+
181
+	if err := d.cmd.Start(); err != nil {
182
+		return fmt.Errorf("[%s] could not start daemon container: %v", d.id, err)
183
+	}
184
+
185
+	wait := make(chan error)
186
+
187
+	go func() {
188
+		wait <- d.cmd.Wait()
189
+		d.c.Logf("[%s] exiting daemon", d.id)
190
+		close(wait)
191
+	}()
192
+
193
+	d.wait = wait
194
+
195
+	tick := time.Tick(500 * time.Millisecond)
196
+	// make sure daemon is ready to receive requests
197
+	startTime := time.Now().Unix()
198
+	for {
199
+		d.c.Logf("[%s] waiting for daemon to start", d.id)
200
+		if time.Now().Unix()-startTime > 5 {
201
+			// After 5 seconds, give up
202
+			return fmt.Errorf("[%s] Daemon exited and never started", d.id)
203
+		}
204
+		select {
205
+		case <-time.After(2 * time.Second):
206
+			return fmt.Errorf("[%s] timeout: daemon does not respond", d.id)
207
+		case <-tick:
208
+			clientConfig, err := d.getClientConfig()
209
+			if err != nil {
210
+				return err
211
+			}
212
+
213
+			client := &http.Client{
214
+				Transport: clientConfig.transport,
215
+			}
216
+
217
+			req, err := http.NewRequest("GET", "/_ping", nil)
218
+			d.c.Assert(err, check.IsNil, check.Commentf("[%s] could not create new request", d.id))
219
+			req.URL.Host = clientConfig.addr
220
+			req.URL.Scheme = clientConfig.scheme
221
+			resp, err := client.Do(req)
222
+			if err != nil {
223
+				continue
224
+			}
225
+			if resp.StatusCode != http.StatusOK {
226
+				d.c.Logf("[%s] received status != 200 OK: %s", d.id, resp.Status)
227
+			}
228
+			d.c.Logf("[%s] daemon started", d.id)
229
+			d.root, err = d.queryRootDir()
230
+			if err != nil {
231
+				return fmt.Errorf("[%s] error querying daemon for root directory: %v", d.id, err)
232
+			}
233
+			return nil
234
+		}
235
+	}
236
+}
237
+
238
+// StartWithBusybox will first start the daemon with Daemon.Start()
239
+// then save the busybox image from the main daemon and load it into this Daemon instance.
240
+func (d *Daemon) StartWithBusybox(arg ...string) error {
241
+	if err := d.Start(arg...); err != nil {
242
+		return err
243
+	}
244
+	return d.LoadBusybox()
245
+}
246
+
247
+// Stop will send a SIGINT every second and wait for the daemon to stop.
248
+// If it timeouts, a SIGKILL is sent.
249
+// Stop will not delete the daemon directory. If a purged daemon is needed,
250
+// instantiate a new one with NewDaemon.
251
+func (d *Daemon) Stop() error {
252
+	if d.cmd == nil || d.wait == nil {
253
+		return errors.New("daemon not started")
254
+	}
255
+
256
+	defer func() {
257
+		d.logFile.Close()
258
+		d.cmd = nil
259
+	}()
260
+
261
+	i := 1
262
+	tick := time.Tick(time.Second)
263
+
264
+	if err := d.cmd.Process.Signal(os.Interrupt); err != nil {
265
+		return fmt.Errorf("could not send signal: %v", err)
266
+	}
267
+out1:
268
+	for {
269
+		select {
270
+		case err := <-d.wait:
271
+			return err
272
+		case <-time.After(15 * time.Second):
273
+			// time for stopping jobs and run onShutdown hooks
274
+			d.c.Log("timeout")
275
+			break out1
276
+		}
277
+	}
278
+
279
+out2:
280
+	for {
281
+		select {
282
+		case err := <-d.wait:
283
+			return err
284
+		case <-tick:
285
+			i++
286
+			if i > 4 {
287
+				d.c.Logf("tried to interrupt daemon for %d times, now try to kill it", i)
288
+				break out2
289
+			}
290
+			d.c.Logf("Attempt #%d: daemon is still running with pid %d", i, d.cmd.Process.Pid)
291
+			if err := d.cmd.Process.Signal(os.Interrupt); err != nil {
292
+				return fmt.Errorf("could not send signal: %v", err)
293
+			}
294
+		}
295
+	}
296
+
297
+	if err := d.cmd.Process.Kill(); err != nil {
298
+		d.c.Logf("Could not kill daemon: %v", err)
299
+		return err
300
+	}
301
+
302
+	return nil
303
+}
304
+
305
+// Restart will restart the daemon by first stopping it and then starting it.
306
+func (d *Daemon) Restart(arg ...string) error {
307
+	d.Stop()
308
+	// in the case of tests running a user namespace-enabled daemon, we have resolved
309
+	// d.root to be the actual final path of the graph dir after the "uid.gid" of
310
+	// remapped root is added--we need to subtract it from the path before calling
311
+	// start or else we will continue making subdirectories rather than truly restarting
312
+	// with the same location/root:
313
+	if root := os.Getenv("DOCKER_REMAP_ROOT"); root != "" {
314
+		d.root = filepath.Dir(d.root)
315
+	}
316
+	return d.Start(arg...)
317
+}
318
+
319
+// LoadBusybox will load the stored busybox into a newly started daemon
320
+func (d *Daemon) LoadBusybox() error {
321
+	bb := filepath.Join(d.folder, "busybox.tar")
322
+	if _, err := os.Stat(bb); err != nil {
323
+		if !os.IsNotExist(err) {
324
+			return fmt.Errorf("unexpected error on busybox.tar stat: %v", err)
325
+		}
326
+		// saving busybox image from main daemon
327
+		if err := exec.Command(dockerBinary, "save", "--output", bb, "busybox:latest").Run(); err != nil {
328
+			return fmt.Errorf("could not save busybox image: %v", err)
329
+		}
330
+	}
331
+	// loading busybox image to this daemon
332
+	if out, err := d.Cmd("load", "--input", bb); err != nil {
333
+		return fmt.Errorf("could not load busybox image: %s", out)
334
+	}
335
+	if err := os.Remove(bb); err != nil {
336
+		d.c.Logf("could not remove %s: %v", bb, err)
337
+	}
338
+	return nil
339
+}
340
+
341
+func (d *Daemon) queryRootDir() (string, error) {
342
+	// update daemon root by asking /info endpoint (to support user
343
+	// namespaced daemon with root remapped uid.gid directory)
344
+	clientConfig, err := d.getClientConfig()
345
+	if err != nil {
346
+		return "", err
347
+	}
348
+
349
+	client := &http.Client{
350
+		Transport: clientConfig.transport,
351
+	}
352
+
353
+	req, err := http.NewRequest("GET", "/info", nil)
354
+	if err != nil {
355
+		return "", err
356
+	}
357
+	req.Header.Set("Content-Type", "application/json")
358
+	req.URL.Host = clientConfig.addr
359
+	req.URL.Scheme = clientConfig.scheme
360
+
361
+	resp, err := client.Do(req)
362
+	if err != nil {
363
+		return "", err
364
+	}
365
+	body := ioutils.NewReadCloserWrapper(resp.Body, func() error {
366
+		return resp.Body.Close()
367
+	})
368
+
369
+	type Info struct {
370
+		DockerRootDir string
371
+	}
372
+	var b []byte
373
+	var i Info
374
+	b, err = readBody(body)
375
+	if err == nil && resp.StatusCode == 200 {
376
+		// read the docker root dir
377
+		if err = json.Unmarshal(b, &i); err == nil {
378
+			return i.DockerRootDir, nil
379
+		}
380
+	}
381
+	return "", err
382
+}
383
+
384
+func (d *Daemon) sock() string {
385
+	return fmt.Sprintf("unix://%s/docker.sock", d.folder)
386
+}
387
+
388
+func (d *Daemon) waitRun(contID string) error {
389
+	args := []string{"--host", d.sock()}
390
+	return waitInspectWithArgs(contID, "{{.State.Running}}", "true", 10*time.Second, args...)
391
+}
392
+
393
+func (d *Daemon) getBaseDeviceSize(c *check.C) int64 {
394
+	infoCmdOutput, _, err := runCommandPipelineWithOutput(
395
+		exec.Command(dockerBinary, "-H", d.sock(), "info"),
396
+		exec.Command("grep", "Base Device Size"),
397
+	)
398
+	c.Assert(err, checker.IsNil)
399
+	basesizeSlice := strings.Split(infoCmdOutput, ":")
400
+	basesize := strings.Trim(basesizeSlice[1], " ")
401
+	basesize = strings.Trim(basesize, "\n")[:len(basesize)-3]
402
+	basesizeFloat, err := strconv.ParseFloat(strings.Trim(basesize, " "), 64)
403
+	c.Assert(err, checker.IsNil)
404
+	basesizeBytes := int64(basesizeFloat) * (1024 * 1024 * 1024)
405
+	return basesizeBytes
406
+}
407
+
408
+// Cmd will execute a docker CLI command against this Daemon.
409
+// Example: d.Cmd("version") will run docker -H unix://path/to/unix.sock version
410
+func (d *Daemon) Cmd(name string, arg ...string) (string, error) {
411
+	args := []string{"--host", d.sock(), name}
412
+	args = append(args, arg...)
413
+	c := exec.Command(dockerBinary, args...)
414
+	b, err := c.CombinedOutput()
415
+	return string(b), err
416
+}
417
+
418
+// CmdWithArgs will execute a docker CLI command against a daemon with the
419
+// given additional arguments
420
+func (d *Daemon) CmdWithArgs(daemonArgs []string, name string, arg ...string) (string, error) {
421
+	args := append(daemonArgs, name)
422
+	args = append(args, arg...)
423
+	c := exec.Command(dockerBinary, args...)
424
+	b, err := c.CombinedOutput()
425
+	return string(b), err
426
+}
427
+
428
+// LogFileName returns the path the the daemon's log file
429
+func (d *Daemon) LogFileName() string {
430
+	return d.logFile.Name()
431
+}
432
+
433
+func (d *Daemon) getIDByName(name string) (string, error) {
434
+	return d.inspectFieldWithError(name, "Id")
435
+}
436
+
437
+func (d *Daemon) inspectFilter(name, filter string) (string, error) {
438
+	format := fmt.Sprintf("{{%s}}", filter)
439
+	out, err := d.Cmd("inspect", "-f", format, name)
440
+	if err != nil {
441
+		return "", fmt.Errorf("failed to inspect %s: %s", name, out)
442
+	}
443
+	return strings.TrimSpace(out), nil
444
+}
445
+
446
+func (d *Daemon) inspectFieldWithError(name, field string) (string, error) {
447
+	return d.inspectFilter(name, fmt.Sprintf(".%s", field))
448
+}
449
+
450
+func (d *Daemon) findContainerIP(id string) string {
451
+	out, err := d.Cmd("inspect", fmt.Sprintf("--format='{{ .NetworkSettings.Networks.bridge.IPAddress }}'"), id)
452
+	if err != nil {
453
+		d.c.Log(err)
454
+	}
455
+	return strings.Trim(out, " \r\n'")
456
+}
... ...
@@ -25,11 +25,9 @@ import (
25 25
 	"github.com/docker/docker/opts"
26 26
 	"github.com/docker/docker/pkg/httputils"
27 27
 	"github.com/docker/docker/pkg/integration"
28
-	"github.com/docker/docker/pkg/integration/checker"
29 28
 	"github.com/docker/docker/pkg/ioutils"
30 29
 	"github.com/docker/docker/pkg/stringutils"
31 30
 	"github.com/docker/engine-api/types"
32
-	"github.com/docker/go-connections/sockets"
33 31
 	"github.com/docker/go-connections/tlsconfig"
34 32
 	"github.com/docker/go-units"
35 33
 	"github.com/go-check/check"
... ...
@@ -102,391 +100,6 @@ func init() {
102 102
 	}
103 103
 }
104 104
 
105
-// Daemon represents a Docker daemon for the testing framework.
106
-type Daemon struct {
107
-	// Defaults to "daemon"
108
-	// Useful to set to --daemon or -d for checking backwards compatibility
109
-	Command     string
110
-	GlobalFlags []string
111
-
112
-	id                string
113
-	c                 *check.C
114
-	logFile           *os.File
115
-	folder            string
116
-	root              string
117
-	stdin             io.WriteCloser
118
-	stdout, stderr    io.ReadCloser
119
-	cmd               *exec.Cmd
120
-	storageDriver     string
121
-	wait              chan error
122
-	userlandProxy     bool
123
-	useDefaultHost    bool
124
-	useDefaultTLSHost bool
125
-}
126
-
127
-type clientConfig struct {
128
-	transport *http.Transport
129
-	scheme    string
130
-	addr      string
131
-}
132
-
133
-// NewDaemon returns a Daemon instance to be used for testing.
134
-// This will create a directory such as d123456789 in the folder specified by $DEST.
135
-// The daemon will not automatically start.
136
-func NewDaemon(c *check.C) *Daemon {
137
-	dest := os.Getenv("DEST")
138
-	c.Assert(dest, check.Not(check.Equals), "", check.Commentf("Please set the DEST environment variable"))
139
-
140
-	id := fmt.Sprintf("d%d", time.Now().UnixNano()%100000000)
141
-	dir := filepath.Join(dest, id)
142
-	daemonFolder, err := filepath.Abs(dir)
143
-	c.Assert(err, check.IsNil, check.Commentf("Could not make %q an absolute path", dir))
144
-	daemonRoot := filepath.Join(daemonFolder, "root")
145
-
146
-	c.Assert(os.MkdirAll(daemonRoot, 0755), check.IsNil, check.Commentf("Could not create daemon root %q", dir))
147
-
148
-	userlandProxy := true
149
-	if env := os.Getenv("DOCKER_USERLANDPROXY"); env != "" {
150
-		if val, err := strconv.ParseBool(env); err != nil {
151
-			userlandProxy = val
152
-		}
153
-	}
154
-
155
-	return &Daemon{
156
-		Command:       "daemon",
157
-		id:            id,
158
-		c:             c,
159
-		folder:        daemonFolder,
160
-		root:          daemonRoot,
161
-		storageDriver: os.Getenv("DOCKER_GRAPHDRIVER"),
162
-		userlandProxy: userlandProxy,
163
-	}
164
-}
165
-
166
-func (d *Daemon) getClientConfig() (*clientConfig, error) {
167
-	var (
168
-		transport *http.Transport
169
-		scheme    string
170
-		addr      string
171
-		proto     string
172
-	)
173
-	if d.useDefaultTLSHost {
174
-		option := &tlsconfig.Options{
175
-			CAFile:   "fixtures/https/ca.pem",
176
-			CertFile: "fixtures/https/client-cert.pem",
177
-			KeyFile:  "fixtures/https/client-key.pem",
178
-		}
179
-		tlsConfig, err := tlsconfig.Client(*option)
180
-		if err != nil {
181
-			return nil, err
182
-		}
183
-		transport = &http.Transport{
184
-			TLSClientConfig: tlsConfig,
185
-		}
186
-		addr = fmt.Sprintf("%s:%d", opts.DefaultHTTPHost, opts.DefaultTLSHTTPPort)
187
-		scheme = "https"
188
-		proto = "tcp"
189
-	} else if d.useDefaultHost {
190
-		addr = opts.DefaultUnixSocket
191
-		proto = "unix"
192
-		scheme = "http"
193
-		transport = &http.Transport{}
194
-	} else {
195
-		addr = filepath.Join(d.folder, "docker.sock")
196
-		proto = "unix"
197
-		scheme = "http"
198
-		transport = &http.Transport{}
199
-	}
200
-
201
-	d.c.Assert(sockets.ConfigureTransport(transport, proto, addr), check.IsNil)
202
-
203
-	return &clientConfig{
204
-		transport: transport,
205
-		scheme:    scheme,
206
-		addr:      addr,
207
-	}, nil
208
-}
209
-
210
-// Start will start the daemon and return once it is ready to receive requests.
211
-// You can specify additional daemon flags.
212
-func (d *Daemon) Start(args ...string) error {
213
-	logFile, err := os.OpenFile(filepath.Join(d.folder, "docker.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
214
-	d.c.Assert(err, check.IsNil, check.Commentf("[%s] Could not create %s/docker.log", d.id, d.folder))
215
-
216
-	return d.StartWithLogFile(logFile, args...)
217
-}
218
-
219
-// StartWithLogFile will start the daemon and attach its streams to a given file.
220
-func (d *Daemon) StartWithLogFile(out *os.File, providedArgs ...string) error {
221
-	dockerBinary, err := exec.LookPath(dockerBinary)
222
-	d.c.Assert(err, check.IsNil, check.Commentf("[%s] could not find docker binary in $PATH", d.id))
223
-
224
-	args := append(d.GlobalFlags,
225
-		d.Command,
226
-		"--graph", d.root,
227
-		"--pidfile", fmt.Sprintf("%s/docker.pid", d.folder),
228
-		fmt.Sprintf("--userland-proxy=%t", d.userlandProxy),
229
-	)
230
-	if !(d.useDefaultHost || d.useDefaultTLSHost) {
231
-		args = append(args, []string{"--host", d.sock()}...)
232
-	}
233
-	if root := os.Getenv("DOCKER_REMAP_ROOT"); root != "" {
234
-		args = append(args, []string{"--userns-remap", root}...)
235
-	}
236
-
237
-	// If we don't explicitly set the log-level or debug flag(-D) then
238
-	// turn on debug mode
239
-	foundLog := false
240
-	foundSd := false
241
-	for _, a := range providedArgs {
242
-		if strings.Contains(a, "--log-level") || strings.Contains(a, "-D") || strings.Contains(a, "--debug") {
243
-			foundLog = true
244
-		}
245
-		if strings.Contains(a, "--storage-driver") {
246
-			foundSd = true
247
-		}
248
-	}
249
-	if !foundLog {
250
-		args = append(args, "--debug")
251
-	}
252
-	if d.storageDriver != "" && !foundSd {
253
-		args = append(args, "--storage-driver", d.storageDriver)
254
-	}
255
-
256
-	args = append(args, providedArgs...)
257
-	d.cmd = exec.Command(dockerBinary, args...)
258
-
259
-	d.cmd.Stdout = out
260
-	d.cmd.Stderr = out
261
-	d.logFile = out
262
-
263
-	if err := d.cmd.Start(); err != nil {
264
-		return fmt.Errorf("[%s] could not start daemon container: %v", d.id, err)
265
-	}
266
-
267
-	wait := make(chan error)
268
-
269
-	go func() {
270
-		wait <- d.cmd.Wait()
271
-		d.c.Logf("[%s] exiting daemon", d.id)
272
-		close(wait)
273
-	}()
274
-
275
-	d.wait = wait
276
-
277
-	tick := time.Tick(500 * time.Millisecond)
278
-	// make sure daemon is ready to receive requests
279
-	startTime := time.Now().Unix()
280
-	for {
281
-		d.c.Logf("[%s] waiting for daemon to start", d.id)
282
-		if time.Now().Unix()-startTime > 5 {
283
-			// After 5 seconds, give up
284
-			return fmt.Errorf("[%s] Daemon exited and never started", d.id)
285
-		}
286
-		select {
287
-		case <-time.After(2 * time.Second):
288
-			return fmt.Errorf("[%s] timeout: daemon does not respond", d.id)
289
-		case <-tick:
290
-			clientConfig, err := d.getClientConfig()
291
-			if err != nil {
292
-				return err
293
-			}
294
-
295
-			client := &http.Client{
296
-				Transport: clientConfig.transport,
297
-			}
298
-
299
-			req, err := http.NewRequest("GET", "/_ping", nil)
300
-			d.c.Assert(err, check.IsNil, check.Commentf("[%s] could not create new request", d.id))
301
-			req.URL.Host = clientConfig.addr
302
-			req.URL.Scheme = clientConfig.scheme
303
-			resp, err := client.Do(req)
304
-			if err != nil {
305
-				continue
306
-			}
307
-			if resp.StatusCode != http.StatusOK {
308
-				d.c.Logf("[%s] received status != 200 OK: %s", d.id, resp.Status)
309
-			}
310
-			d.c.Logf("[%s] daemon started", d.id)
311
-			d.root, err = d.queryRootDir()
312
-			if err != nil {
313
-				return fmt.Errorf("[%s] error querying daemon for root directory: %v", d.id, err)
314
-			}
315
-			return nil
316
-		}
317
-	}
318
-}
319
-
320
-// StartWithBusybox will first start the daemon with Daemon.Start()
321
-// then save the busybox image from the main daemon and load it into this Daemon instance.
322
-func (d *Daemon) StartWithBusybox(arg ...string) error {
323
-	if err := d.Start(arg...); err != nil {
324
-		return err
325
-	}
326
-	return d.LoadBusybox()
327
-}
328
-
329
-// Stop will send a SIGINT every second and wait for the daemon to stop.
330
-// If it timeouts, a SIGKILL is sent.
331
-// Stop will not delete the daemon directory. If a purged daemon is needed,
332
-// instantiate a new one with NewDaemon.
333
-func (d *Daemon) Stop() error {
334
-	if d.cmd == nil || d.wait == nil {
335
-		return errors.New("daemon not started")
336
-	}
337
-
338
-	defer func() {
339
-		d.logFile.Close()
340
-		d.cmd = nil
341
-	}()
342
-
343
-	i := 1
344
-	tick := time.Tick(time.Second)
345
-
346
-	if err := d.cmd.Process.Signal(os.Interrupt); err != nil {
347
-		return fmt.Errorf("could not send signal: %v", err)
348
-	}
349
-out1:
350
-	for {
351
-		select {
352
-		case err := <-d.wait:
353
-			return err
354
-		case <-time.After(15 * time.Second):
355
-			// time for stopping jobs and run onShutdown hooks
356
-			d.c.Log("timeout")
357
-			break out1
358
-		}
359
-	}
360
-
361
-out2:
362
-	for {
363
-		select {
364
-		case err := <-d.wait:
365
-			return err
366
-		case <-tick:
367
-			i++
368
-			if i > 4 {
369
-				d.c.Logf("tried to interrupt daemon for %d times, now try to kill it", i)
370
-				break out2
371
-			}
372
-			d.c.Logf("Attempt #%d: daemon is still running with pid %d", i, d.cmd.Process.Pid)
373
-			if err := d.cmd.Process.Signal(os.Interrupt); err != nil {
374
-				return fmt.Errorf("could not send signal: %v", err)
375
-			}
376
-		}
377
-	}
378
-
379
-	if err := d.cmd.Process.Kill(); err != nil {
380
-		d.c.Logf("Could not kill daemon: %v", err)
381
-		return err
382
-	}
383
-
384
-	return nil
385
-}
386
-
387
-// Restart will restart the daemon by first stopping it and then starting it.
388
-func (d *Daemon) Restart(arg ...string) error {
389
-	d.Stop()
390
-	// in the case of tests running a user namespace-enabled daemon, we have resolved
391
-	// d.root to be the actual final path of the graph dir after the "uid.gid" of
392
-	// remapped root is added--we need to subtract it from the path before calling
393
-	// start or else we will continue making subdirectories rather than truly restarting
394
-	// with the same location/root:
395
-	if root := os.Getenv("DOCKER_REMAP_ROOT"); root != "" {
396
-		d.root = filepath.Dir(d.root)
397
-	}
398
-	return d.Start(arg...)
399
-}
400
-
401
-// LoadBusybox will load the stored busybox into a newly started daemon
402
-func (d *Daemon) LoadBusybox() error {
403
-	bb := filepath.Join(d.folder, "busybox.tar")
404
-	if _, err := os.Stat(bb); err != nil {
405
-		if !os.IsNotExist(err) {
406
-			return fmt.Errorf("unexpected error on busybox.tar stat: %v", err)
407
-		}
408
-		// saving busybox image from main daemon
409
-		if err := exec.Command(dockerBinary, "save", "--output", bb, "busybox:latest").Run(); err != nil {
410
-			return fmt.Errorf("could not save busybox image: %v", err)
411
-		}
412
-	}
413
-	// loading busybox image to this daemon
414
-	if out, err := d.Cmd("load", "--input", bb); err != nil {
415
-		return fmt.Errorf("could not load busybox image: %s", out)
416
-	}
417
-	if err := os.Remove(bb); err != nil {
418
-		d.c.Logf("could not remove %s: %v", bb, err)
419
-	}
420
-	return nil
421
-}
422
-
423
-func (d *Daemon) queryRootDir() (string, error) {
424
-	// update daemon root by asking /info endpoint (to support user
425
-	// namespaced daemon with root remapped uid.gid directory)
426
-	clientConfig, err := d.getClientConfig()
427
-	if err != nil {
428
-		return "", err
429
-	}
430
-
431
-	client := &http.Client{
432
-		Transport: clientConfig.transport,
433
-	}
434
-
435
-	req, err := http.NewRequest("GET", "/info", nil)
436
-	if err != nil {
437
-		return "", err
438
-	}
439
-	req.Header.Set("Content-Type", "application/json")
440
-	req.URL.Host = clientConfig.addr
441
-	req.URL.Scheme = clientConfig.scheme
442
-
443
-	resp, err := client.Do(req)
444
-	if err != nil {
445
-		return "", err
446
-	}
447
-	body := ioutils.NewReadCloserWrapper(resp.Body, func() error {
448
-		return resp.Body.Close()
449
-	})
450
-
451
-	type Info struct {
452
-		DockerRootDir string
453
-	}
454
-	var b []byte
455
-	var i Info
456
-	b, err = readBody(body)
457
-	if err == nil && resp.StatusCode == 200 {
458
-		// read the docker root dir
459
-		if err = json.Unmarshal(b, &i); err == nil {
460
-			return i.DockerRootDir, nil
461
-		}
462
-	}
463
-	return "", err
464
-}
465
-
466
-func (d *Daemon) sock() string {
467
-	return fmt.Sprintf("unix://%s/docker.sock", d.folder)
468
-}
469
-
470
-func (d *Daemon) waitRun(contID string) error {
471
-	args := []string{"--host", d.sock()}
472
-	return waitInspectWithArgs(contID, "{{.State.Running}}", "true", 10*time.Second, args...)
473
-}
474
-
475
-func (d *Daemon) getBaseDeviceSize(c *check.C) int64 {
476
-	infoCmdOutput, _, err := runCommandPipelineWithOutput(
477
-		exec.Command(dockerBinary, "-H", d.sock(), "info"),
478
-		exec.Command("grep", "Base Device Size"),
479
-	)
480
-	c.Assert(err, checker.IsNil)
481
-	basesizeSlice := strings.Split(infoCmdOutput, ":")
482
-	basesize := strings.Trim(basesizeSlice[1], " ")
483
-	basesize = strings.Trim(basesize, "\n")[:len(basesize)-3]
484
-	basesizeFloat, err := strconv.ParseFloat(strings.Trim(basesize, " "), 64)
485
-	c.Assert(err, checker.IsNil)
486
-	basesizeBytes := int64(basesizeFloat) * (1024 * 1024 * 1024)
487
-	return basesizeBytes
488
-}
489
-
490 105
 func convertBasesize(basesizeBytes int64) (int64, error) {
491 106
 	basesize := units.HumanSize(float64(basesizeBytes))
492 107
 	basesize = strings.Trim(basesize, " ")[:len(basesize)-3]
... ...
@@ -497,48 +110,6 @@ func convertBasesize(basesizeBytes int64) (int64, error) {
497 497
 	return int64(basesizeFloat) * 1024 * 1024 * 1024, nil
498 498
 }
499 499
 
500
-// Cmd will execute a docker CLI command against this Daemon.
501
-// Example: d.Cmd("version") will run docker -H unix://path/to/unix.sock version
502
-func (d *Daemon) Cmd(name string, arg ...string) (string, error) {
503
-	args := []string{"--host", d.sock(), name}
504
-	args = append(args, arg...)
505
-	c := exec.Command(dockerBinary, args...)
506
-	b, err := c.CombinedOutput()
507
-	return string(b), err
508
-}
509
-
510
-// CmdWithArgs will execute a docker CLI command against a daemon with the
511
-// given additional arguments
512
-func (d *Daemon) CmdWithArgs(daemonArgs []string, name string, arg ...string) (string, error) {
513
-	args := append(daemonArgs, name)
514
-	args = append(args, arg...)
515
-	c := exec.Command(dockerBinary, args...)
516
-	b, err := c.CombinedOutput()
517
-	return string(b), err
518
-}
519
-
520
-// LogFileName returns the path the the daemon's log file
521
-func (d *Daemon) LogFileName() string {
522
-	return d.logFile.Name()
523
-}
524
-
525
-func (d *Daemon) getIDByName(name string) (string, error) {
526
-	return d.inspectFieldWithError(name, "Id")
527
-}
528
-
529
-func (d *Daemon) inspectFilter(name, filter string) (string, error) {
530
-	format := fmt.Sprintf("{{%s}}", filter)
531
-	out, err := d.Cmd("inspect", "-f", format, name)
532
-	if err != nil {
533
-		return "", fmt.Errorf("failed to inspect %s: %s", name, out)
534
-	}
535
-	return strings.TrimSpace(out), nil
536
-}
537
-
538
-func (d *Daemon) inspectFieldWithError(name, field string) (string, error) {
539
-	return d.inspectFilter(name, fmt.Sprintf(".%s", field))
540
-}
541
-
542 500
 func daemonHost() string {
543 501
 	daemonURLStr := "unix://" + opts.DefaultUnixSocket
544 502
 	if daemonHostVar := os.Getenv("DOCKER_HOST"); daemonHostVar != "" {
... ...
@@ -972,14 +543,6 @@ func findContainerIP(c *check.C, id string, network string) string {
972 972
 	return strings.Trim(out, " \r\n'")
973 973
 }
974 974
 
975
-func (d *Daemon) findContainerIP(id string) string {
976
-	out, err := d.Cmd("inspect", fmt.Sprintf("--format='{{ .NetworkSettings.Networks.bridge.IPAddress }}'"), id)
977
-	if err != nil {
978
-		d.c.Log(err)
979
-	}
980
-	return strings.Trim(out, " \r\n'")
981
-}
982
-
983 975
 func getContainerCount() (int, error) {
984 976
 	const containers = "Containers:"
985 977