Browse code

Refactoring execdriver.Command and Container structs to support 'docker exec' and other similar features in the future.

Docker-DCO-1.1-Signed-off-by: Vishnu Kannan <vishnuk@google.com> (github: vishh)

Vishnu Kannan authored on 2014/08/27 07:05:37
Showing 15 changed files
... ...
@@ -103,7 +103,6 @@ func (daemon *Daemon) ContainerAttach(job *engine.Job) engine.Status {
103 103
 		}
104 104
 
105 105
 		<-daemon.Attach(container, cStdin, cStdinCloser, cStdout, cStderr)
106
-
107 106
 		// If we are in stdinonce mode, wait for the process to end
108 107
 		// otherwise, simply return
109 108
 		if container.Config.StdinOnce && !container.Config.Tty {
... ...
@@ -128,7 +127,7 @@ func (daemon *Daemon) Attach(container *Container, stdin io.ReadCloser, stdinClo
128 128
 
129 129
 	if stdin != nil && container.Config.OpenStdin {
130 130
 		nJobs++
131
-		if cStdin, err := container.StdinPipe(); err != nil {
131
+		if cStdin, err := container.StdConfig.StdinPipe(); err != nil {
132 132
 			errors <- err
133 133
 		} else {
134 134
 			go func() {
... ...
@@ -164,7 +163,7 @@ func (daemon *Daemon) Attach(container *Container, stdin io.ReadCloser, stdinClo
164 164
 	}
165 165
 	if stdout != nil {
166 166
 		nJobs++
167
-		if p, err := container.StdoutPipe(); err != nil {
167
+		if p, err := container.StdConfig.StdoutPipe(); err != nil {
168 168
 			errors <- err
169 169
 		} else {
170 170
 			cStdout = p
... ...
@@ -193,7 +192,7 @@ func (daemon *Daemon) Attach(container *Container, stdin io.ReadCloser, stdinClo
193 193
 			if stdinCloser != nil {
194 194
 				defer stdinCloser.Close()
195 195
 			}
196
-			if cStdout, err := container.StdoutPipe(); err != nil {
196
+			if cStdout, err := container.StdConfig.StdoutPipe(); err != nil {
197 197
 				log.Errorf("attach: stdout pipe: %s", err)
198 198
 			} else {
199 199
 				io.Copy(&utils.NopWriter{}, cStdout)
... ...
@@ -202,7 +201,7 @@ func (daemon *Daemon) Attach(container *Container, stdin io.ReadCloser, stdinClo
202 202
 	}
203 203
 	if stderr != nil {
204 204
 		nJobs++
205
-		if p, err := container.StderrPipe(); err != nil {
205
+		if p, err := container.StdConfig.StderrPipe(); err != nil {
206 206
 			errors <- err
207 207
 		} else {
208 208
 			cStderr = p
... ...
@@ -232,7 +231,7 @@ func (daemon *Daemon) Attach(container *Container, stdin io.ReadCloser, stdinClo
232 232
 				defer stdinCloser.Close()
233 233
 			}
234 234
 
235
-			if cStderr, err := container.StderrPipe(); err != nil {
235
+			if cStderr, err := container.StdConfig.StderrPipe(); err != nil {
236 236
 				log.Errorf("attach: stdout pipe: %s", err)
237 237
 			} else {
238 238
 				io.Copy(&utils.NopWriter{}, cStderr)
... ...
@@ -41,6 +41,13 @@ var (
41 41
 	ErrContainerStartTimeout = errors.New("The container failed to start due to timed out.")
42 42
 )
43 43
 
44
+type StdConfig struct {
45
+	stdout    *broadcastwriter.BroadcastWriter
46
+	stderr    *broadcastwriter.BroadcastWriter
47
+	stdin     io.ReadCloser
48
+	stdinPipe io.WriteCloser
49
+}
50
+
44 51
 type Container struct {
45 52
 	*State
46 53
 	root   string // Path to the "home" of the container, including metadata.
... ...
@@ -66,10 +73,7 @@ type Container struct {
66 66
 	ExecDriver     string
67 67
 
68 68
 	command   *execdriver.Command
69
-	stdout    *broadcastwriter.BroadcastWriter
70
-	stderr    *broadcastwriter.BroadcastWriter
71
-	stdin     io.ReadCloser
72
-	stdinPipe io.WriteCloser
69
+	StdConfig StdConfig
73 70
 
74 71
 	daemon                   *Daemon
75 72
 	MountLabel, ProcessLabel string
... ...
@@ -247,26 +251,31 @@ func populateCommand(c *Container, env []string) error {
247 247
 		CpuShares:  c.Config.CpuShares,
248 248
 		Cpuset:     c.Config.Cpuset,
249 249
 	}
250
+
251
+	processConfig := execdriver.ProcessConfig{
252
+		Privileged: c.hostConfig.Privileged,
253
+		Entrypoint: c.Path,
254
+		Arguments:  c.Args,
255
+		Tty:        c.Config.Tty,
256
+		User:       c.Config.User,
257
+	}
258
+	processConfig.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
259
+	processConfig.Env = env
250 260
 	c.command = &execdriver.Command{
251 261
 		ID:                 c.ID,
252
-		Privileged:         c.hostConfig.Privileged,
253 262
 		Rootfs:             c.RootfsPath(),
254 263
 		InitPath:           "/.dockerinit",
255
-		Entrypoint:         c.Path,
256
-		Arguments:          c.Args,
257 264
 		WorkingDir:         c.Config.WorkingDir,
258 265
 		Network:            en,
259
-		Tty:                c.Config.Tty,
260
-		User:               c.Config.User,
261 266
 		Config:             context,
262 267
 		Resources:          resources,
263 268
 		AllowedDevices:     allowedDevices,
264 269
 		AutoCreatedDevices: autoCreatedDevices,
265 270
 		CapAdd:             c.hostConfig.CapAdd,
266 271
 		CapDrop:            c.hostConfig.CapDrop,
272
+		ProcessConfig:      processConfig,
267 273
 	}
268
-	c.command.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
269
-	c.command.Env = env
274
+
270 275
 	return nil
271 276
 }
272 277
 
... ...
@@ -329,7 +338,7 @@ func (container *Container) Run() error {
329 329
 }
330 330
 
331 331
 func (container *Container) Output() (output []byte, err error) {
332
-	pipe, err := container.StdoutPipe()
332
+	pipe, err := container.StdConfig.StdoutPipe()
333 333
 	if err != nil {
334 334
 		return nil, err
335 335
 	}
... ...
@@ -342,7 +351,7 @@ func (container *Container) Output() (output []byte, err error) {
342 342
 	return output, err
343 343
 }
344 344
 
345
-// Container.StdinPipe returns a WriteCloser which can be used to feed data
345
+// StdConfig.StdinPipe returns a WriteCloser which can be used to feed data
346 346
 // to the standard input of the container's active process.
347 347
 // Container.StdoutPipe and Container.StderrPipe each return a ReadCloser
348 348
 // which can be used to retrieve the standard output (and error) generated
... ...
@@ -350,31 +359,31 @@ func (container *Container) Output() (output []byte, err error) {
350 350
 // copied and delivered to all StdoutPipe and StderrPipe consumers, using
351 351
 // a kind of "broadcaster".
352 352
 
353
-func (container *Container) StdinPipe() (io.WriteCloser, error) {
354
-	return container.stdinPipe, nil
353
+func (stdConfig *StdConfig) StdinPipe() (io.WriteCloser, error) {
354
+	return stdConfig.stdinPipe, nil
355 355
 }
356 356
 
357
-func (container *Container) StdoutPipe() (io.ReadCloser, error) {
357
+func (stdConfig *StdConfig) StdoutPipe() (io.ReadCloser, error) {
358 358
 	reader, writer := io.Pipe()
359
-	container.stdout.AddWriter(writer, "")
359
+	stdConfig.stdout.AddWriter(writer, "")
360 360
 	return utils.NewBufReader(reader), nil
361 361
 }
362 362
 
363
-func (container *Container) StderrPipe() (io.ReadCloser, error) {
363
+func (stdConfig *StdConfig) StderrPipe() (io.ReadCloser, error) {
364 364
 	reader, writer := io.Pipe()
365
-	container.stderr.AddWriter(writer, "")
365
+	stdConfig.stderr.AddWriter(writer, "")
366 366
 	return utils.NewBufReader(reader), nil
367 367
 }
368 368
 
369 369
 func (container *Container) StdoutLogPipe() io.ReadCloser {
370 370
 	reader, writer := io.Pipe()
371
-	container.stdout.AddWriter(writer, "stdout")
371
+	container.StdConfig.stdout.AddWriter(writer, "stdout")
372 372
 	return utils.NewBufReader(reader)
373 373
 }
374 374
 
375 375
 func (container *Container) StderrLogPipe() io.ReadCloser {
376 376
 	reader, writer := io.Pipe()
377
-	container.stderr.AddWriter(writer, "stderr")
377
+	container.StdConfig.stderr.AddWriter(writer, "stderr")
378 378
 	return utils.NewBufReader(reader)
379 379
 }
380 380
 
... ...
@@ -631,7 +640,7 @@ func (container *Container) Restart(seconds int) error {
631 631
 }
632 632
 
633 633
 func (container *Container) Resize(h, w int) error {
634
-	return container.command.Terminal.Resize(h, w)
634
+	return container.command.ProcessConfig.Terminal.Resize(h, w)
635 635
 }
636 636
 
637 637
 func (container *Container) ExportRw() (archive.Archive, error) {
... ...
@@ -815,7 +824,7 @@ func (container *Container) Exposes(p nat.Port) bool {
815 815
 }
816 816
 
817 817
 func (container *Container) GetPtyMaster() (*os.File, error) {
818
-	ttyConsole, ok := container.command.Terminal.(execdriver.TtyTerminal)
818
+	ttyConsole, ok := container.command.ProcessConfig.Terminal.(execdriver.TtyTerminal)
819 819
 	if !ok {
820 820
 		return nil, ErrNoTTY
821 821
 	}
... ...
@@ -1083,11 +1092,11 @@ func (container *Container) startLoggingToDisk() error {
1083 1083
 		return err
1084 1084
 	}
1085 1085
 
1086
-	if err := container.daemon.LogToDisk(container.stdout, pth, "stdout"); err != nil {
1086
+	if err := container.daemon.LogToDisk(container.StdConfig.stdout, pth, "stdout"); err != nil {
1087 1087
 		return err
1088 1088
 	}
1089 1089
 
1090
-	if err := container.daemon.LogToDisk(container.stderr, pth, "stderr"); err != nil {
1090
+	if err := container.daemon.LogToDisk(container.StdConfig.stderr, pth, "stderr"); err != nil {
1091 1091
 		return err
1092 1092
 	}
1093 1093
 
... ...
@@ -195,13 +195,13 @@ func (daemon *Daemon) register(container *Container, updateSuffixarray bool) err
195 195
 	container.daemon = daemon
196 196
 
197 197
 	// Attach to stdout and stderr
198
-	container.stderr = broadcastwriter.New()
199
-	container.stdout = broadcastwriter.New()
198
+	container.StdConfig.stderr = broadcastwriter.New()
199
+	container.StdConfig.stdout = broadcastwriter.New()
200 200
 	// Attach to stdin
201 201
 	if container.Config.OpenStdin {
202
-		container.stdin, container.stdinPipe = io.Pipe()
202
+		container.StdConfig.stdin, container.StdConfig.stdinPipe = io.Pipe()
203 203
 	} else {
204
-		container.stdinPipe = utils.NopWriteCloser(ioutil.Discard) // Silently drop stdin
204
+		container.StdConfig.stdinPipe = utils.NopWriteCloser(ioutil.Discard) // Silently drop stdin
205 205
 	}
206 206
 	// done
207 207
 	daemon.containers.Add(container.ID, container)
... ...
@@ -229,7 +229,7 @@ func (daemon *Daemon) register(container *Container, updateSuffixarray bool) err
229 229
 				ID: container.ID,
230 230
 			}
231 231
 			var err error
232
-			cmd.Process, err = os.FindProcess(existingPid)
232
+			cmd.ProcessConfig.Process, err = os.FindProcess(existingPid)
233 233
 			if err != nil {
234 234
 				log.Debugf("cannot find existing process for %d", existingPid)
235 235
 			}
... ...
@@ -20,7 +20,7 @@ var (
20 20
 	ErrDriverNotFound          = errors.New("The requested docker init has not been found")
21 21
 )
22 22
 
23
-type StartCallback func(*Command)
23
+type StartCallback func(*ProcessConfig)
24 24
 
25 25
 // Driver specific information based on
26 26
 // processes registered with the driver
... ...
@@ -80,20 +80,27 @@ type Mount struct {
80 80
 	Private     bool   `json:"private"`
81 81
 }
82 82
 
83
-// Process wrapps an os/exec.Cmd to add more metadata
84
-type Command struct {
83
+// Describes a process that will be run inside a container.
84
+type ProcessConfig struct {
85 85
 	exec.Cmd `json:"-"`
86 86
 
87
+	Privileged   bool     `json:"privileged"`
88
+	User         string   `json:"user"`
89
+	Tty          bool     `json:"tty"`
90
+	Entrypoint   string   `json:"entrypoint"`
91
+	Arguments    []string `json:"arguments"`
92
+	Terminal     Terminal `json:"-"`             // standard or tty terminal
93
+	ContainerPid int      `json:"container_pid"` // the pid for the process inside a container
94
+	Console      string   `json:"-"`             // dev/console path
95
+}
96
+
97
+// Process wrapps an os/exec.Cmd to add more metadata
98
+type Command struct {
87 99
 	ID                 string              `json:"id"`
88
-	Privileged         bool                `json:"privileged"`
89
-	User               string              `json:"user"`
90 100
 	Rootfs             string              `json:"rootfs"`   // root fs of the container
91 101
 	InitPath           string              `json:"initpath"` // dockerinit
92
-	Entrypoint         string              `json:"entrypoint"`
93
-	Arguments          []string            `json:"arguments"`
94 102
 	WorkingDir         string              `json:"working_dir"`
95 103
 	ConfigPath         string              `json:"config_path"` // this should be able to be removed when the lxc template is moved into the driver
96
-	Tty                bool                `json:"tty"`
97 104
 	Network            *Network            `json:"network"`
98 105
 	Config             map[string][]string `json:"config"` //  generic values that specific drivers can consume
99 106
 	Resources          *Resources          `json:"resources"`
... ...
@@ -103,13 +110,11 @@ type Command struct {
103 103
 	CapAdd             []string            `json:"cap_add"`
104 104
 	CapDrop            []string            `json:"cap_drop"`
105 105
 
106
-	Terminal     Terminal `json:"-"`             // standard or tty terminal
107
-	Console      string   `json:"-"`             // dev/console path
108
-	ContainerPid int      `json:"container_pid"` // the pid for the process inside a container
106
+	ProcessConfig ProcessConfig `json:"process_config"` // Describes the init process of the container.
109 107
 }
110 108
 
111 109
 // Return the pid of the process
112 110
 // If the process is nil -1 will be returned
113
-func (c *Command) Pid() int {
114
-	return c.ContainerPid
111
+func (processConfig *ProcessConfig) Pid() int {
112
+	return processConfig.ContainerPid
115 113
 }
... ...
@@ -59,12 +59,12 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
59 59
 		err  error
60 60
 	)
61 61
 
62
-	if c.Tty {
63
-		term, err = NewTtyConsole(c, pipes)
62
+	if c.ProcessConfig.Tty {
63
+		term, err = NewTtyConsole(&c.ProcessConfig, pipes)
64 64
 	} else {
65
-		term, err = execdriver.NewStdConsole(c, pipes)
65
+		term, err = execdriver.NewStdConsole(&c.ProcessConfig, pipes)
66 66
 	}
67
-	c.Terminal = term
67
+	c.ProcessConfig.Terminal = term
68 68
 
69 69
 	c.Mounts = append(c.Mounts, execdriver.Mount{
70 70
 		Source:      d.initPath,
... ...
@@ -98,11 +98,11 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
98 98
 		"-mtu", strconv.Itoa(c.Network.Mtu),
99 99
 	)
100 100
 
101
-	if c.User != "" {
102
-		params = append(params, "-u", c.User)
101
+	if c.ProcessConfig.User != "" {
102
+		params = append(params, "-u", c.ProcessConfig.User)
103 103
 	}
104 104
 
105
-	if c.Privileged {
105
+	if c.ProcessConfig.Privileged {
106 106
 		if d.apparmor {
107 107
 			params[0] = path.Join(d.root, "lxc-start-unconfined")
108 108
 
... ...
@@ -122,8 +122,8 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
122 122
 		params = append(params, fmt.Sprintf("-cap-drop=%s", strings.Join(c.CapDrop, ":")))
123 123
 	}
124 124
 
125
-	params = append(params, "--", c.Entrypoint)
126
-	params = append(params, c.Arguments...)
125
+	params = append(params, "--", c.ProcessConfig.Entrypoint)
126
+	params = append(params, c.ProcessConfig.Arguments...)
127 127
 
128 128
 	if d.sharedRoot {
129 129
 		// lxc-start really needs / to be non-shared, or all kinds of stuff break
... ...
@@ -149,14 +149,14 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
149 149
 	if err != nil {
150 150
 		aname = name
151 151
 	}
152
-	c.Path = aname
153
-	c.Args = append([]string{name}, arg...)
152
+	c.ProcessConfig.Path = aname
153
+	c.ProcessConfig.Args = append([]string{name}, arg...)
154 154
 
155 155
 	if err := nodes.CreateDeviceNodes(c.Rootfs, c.AutoCreatedDevices); err != nil {
156 156
 		return -1, err
157 157
 	}
158 158
 
159
-	if err := c.Start(); err != nil {
159
+	if err := c.ProcessConfig.Start(); err != nil {
160 160
 		return -1, err
161 161
 	}
162 162
 
... ...
@@ -166,7 +166,7 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
166 166
 	)
167 167
 
168 168
 	go func() {
169
-		if err := c.Wait(); err != nil {
169
+		if err := c.ProcessConfig.Wait(); err != nil {
170 170
 			if _, ok := err.(*exec.ExitError); !ok { // Do not propagate the error if it's simply a status code != 0
171 171
 				waitErr = err
172 172
 			}
... ...
@@ -177,17 +177,17 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
177 177
 	// Poll lxc for RUNNING status
178 178
 	pid, err := d.waitForStart(c, waitLock)
179 179
 	if err != nil {
180
-		if c.Process != nil {
181
-			c.Process.Kill()
182
-			c.Wait()
180
+		if c.ProcessConfig.Process != nil {
181
+			c.ProcessConfig.Process.Kill()
182
+			c.ProcessConfig.Wait()
183 183
 		}
184 184
 		return -1, err
185 185
 	}
186 186
 
187
-	c.ContainerPid = pid
187
+	c.ProcessConfig.ContainerPid = pid
188 188
 
189 189
 	if startCallback != nil {
190
-		startCallback(c)
190
+		startCallback(&c.ProcessConfig)
191 191
 	}
192 192
 
193 193
 	<-waitLock
... ...
@@ -198,10 +198,10 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
198 198
 /// Return the exit code of the process
199 199
 // if the process has not exited -1 will be returned
200 200
 func getExitCode(c *execdriver.Command) int {
201
-	if c.ProcessState == nil {
201
+	if c.ProcessConfig.ProcessState == nil {
202 202
 		return -1
203 203
 	}
204
-	return c.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
204
+	return c.ProcessConfig.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
205 205
 }
206 206
 
207 207
 func (d *driver) Kill(c *execdriver.Command, sig int) error {
... ...
@@ -442,7 +442,7 @@ func (d *driver) generateLXCConfig(c *execdriver.Command) (string, error) {
442 442
 }
443 443
 
444 444
 func (d *driver) generateEnvConfig(c *execdriver.Command) error {
445
-	data, err := json.Marshal(c.Env)
445
+	data, err := json.Marshal(c.ProcessConfig.Env)
446 446
 	if err != nil {
447 447
 		return err
448 448
 	}
... ...
@@ -462,7 +462,7 @@ type TtyConsole struct {
462 462
 	SlavePty  *os.File
463 463
 }
464 464
 
465
-func NewTtyConsole(command *execdriver.Command, pipes *execdriver.Pipes) (*TtyConsole, error) {
465
+func NewTtyConsole(processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes) (*TtyConsole, error) {
466 466
 	// lxc is special in that we cannot create the master outside of the container without
467 467
 	// opening the slave because we have nothing to provide to the cmd.  We have to open both then do
468 468
 	// the crazy setup on command right now instead of passing the console path to lxc and telling it
... ...
@@ -478,12 +478,12 @@ func NewTtyConsole(command *execdriver.Command, pipes *execdriver.Pipes) (*TtyCo
478 478
 		SlavePty:  ptySlave,
479 479
 	}
480 480
 
481
-	if err := tty.AttachPipes(&command.Cmd, pipes); err != nil {
481
+	if err := tty.AttachPipes(&processConfig.Cmd, pipes); err != nil {
482 482
 		tty.Close()
483 483
 		return nil, err
484 484
 	}
485 485
 
486
-	command.Console = tty.SlavePty.Name()
486
+	processConfig.Console = tty.SlavePty.Name()
487 487
 
488 488
 	return tty, nil
489 489
 }
... ...
@@ -42,7 +42,7 @@ lxc.se_context = {{ .ProcessLabel}}
42 42
 # no controlling tty at all
43 43
 lxc.tty = 1
44 44
 
45
-{{if .Privileged}}
45
+{{if .ProcessConfig.Privileged}}
46 46
 lxc.cgroup.devices.allow = a
47 47
 {{else}}
48 48
 # no implicit access to devices
... ...
@@ -66,7 +66,7 @@ lxc.pivotdir = lxc_putold
66 66
 lxc.mount.entry = proc {{escapeFstabSpaces $ROOTFS}}/proc proc nosuid,nodev,noexec 0 0
67 67
 lxc.mount.entry = sysfs {{escapeFstabSpaces $ROOTFS}}/sys sysfs nosuid,nodev,noexec 0 0
68 68
 
69
-{{if .Tty}}
69
+{{if .ProcessConfig.Tty}}
70 70
 lxc.mount.entry = {{.Console}} {{escapeFstabSpaces $ROOTFS}}/dev/console none bind,rw 0 0
71 71
 {{end}}
72 72
 
... ...
@@ -81,7 +81,7 @@ lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabS
81 81
 {{end}}
82 82
 {{end}}
83 83
 
84
-{{if .Privileged}}
84
+{{if .ProcessConfig.Privileged}}
85 85
 {{if .AppArmor}}
86 86
 lxc.aa_profile = unconfined
87 87
 {{else}}
... ...
@@ -77,9 +77,11 @@ func TestCustomLxcConfig(t *testing.T) {
77 77
 	if err != nil {
78 78
 		t.Fatal(err)
79 79
 	}
80
-	command := &execdriver.Command{
81
-		ID:         "1",
80
+	processConfig := execdriver.ProcessConfig{
82 81
 		Privileged: false,
82
+	}
83
+	command := &execdriver.Command{
84
+		ID: "1",
83 85
 		Config: map[string][]string{
84 86
 			"lxc": {
85 87
 				"lxc.utsname = docker",
... ...
@@ -90,6 +92,7 @@ func TestCustomLxcConfig(t *testing.T) {
90 90
 			Mtu:       1500,
91 91
 			Interface: nil,
92 92
 		},
93
+		ProcessConfig: processConfig,
93 94
 	}
94 95
 
95 96
 	p, err := driver.generateLXCConfig(command)
... ...
@@ -23,11 +23,11 @@ import (
23 23
 func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Config, error) {
24 24
 	container := template.New()
25 25
 
26
-	container.Hostname = getEnv("HOSTNAME", c.Env)
27
-	container.Tty = c.Tty
28
-	container.User = c.User
26
+	container.Hostname = getEnv("HOSTNAME", c.ProcessConfig.Env)
27
+	container.Tty = c.ProcessConfig.Tty
28
+	container.User = c.ProcessConfig.User
29 29
 	container.WorkingDir = c.WorkingDir
30
-	container.Env = c.Env
30
+	container.Env = c.ProcessConfig.Env
31 31
 	container.Cgroups.Name = c.ID
32 32
 	container.Cgroups.AllowedDevices = c.AllowedDevices
33 33
 	container.MountConfig.DeviceNodes = c.AutoCreatedDevices
... ...
@@ -40,7 +40,7 @@ func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Config, e
40 40
 		return nil, err
41 41
 	}
42 42
 
43
-	if c.Privileged {
43
+	if c.ProcessConfig.Privileged {
44 44
 		if err := d.setPrivileged(container); err != nil {
45 45
 			return nil, err
46 46
 		}
... ...
@@ -68,26 +68,26 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
68 68
 
69 69
 	var term execdriver.Terminal
70 70
 
71
-	if c.Tty {
72
-		term, err = NewTtyConsole(c, pipes)
71
+	if c.ProcessConfig.Tty {
72
+		term, err = NewTtyConsole(&c.ProcessConfig, pipes)
73 73
 	} else {
74
-		term, err = execdriver.NewStdConsole(c, pipes)
74
+		term, err = execdriver.NewStdConsole(&c.ProcessConfig, pipes)
75 75
 	}
76 76
 	if err != nil {
77 77
 		return -1, err
78 78
 	}
79
-	c.Terminal = term
79
+	c.ProcessConfig.Terminal = term
80 80
 
81 81
 	d.Lock()
82 82
 	d.activeContainers[c.ID] = &activeContainer{
83 83
 		container: container,
84
-		cmd:       &c.Cmd,
84
+		cmd:       &c.ProcessConfig.Cmd,
85 85
 	}
86 86
 	d.Unlock()
87 87
 
88 88
 	var (
89 89
 		dataPath = filepath.Join(d.root, c.ID)
90
-		args     = append([]string{c.Entrypoint}, c.Arguments...)
90
+		args     = append([]string{c.ProcessConfig.Entrypoint}, c.ProcessConfig.Arguments...)
91 91
 	)
92 92
 
93 93
 	if err := d.createContainerRoot(c.ID); err != nil {
... ...
@@ -99,9 +99,9 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
99 99
 		return -1, err
100 100
 	}
101 101
 
102
-	return namespaces.Exec(container, c.Stdin, c.Stdout, c.Stderr, c.Console, c.Rootfs, dataPath, args, func(container *libcontainer.Config, console, rootfs, dataPath, init string, child *os.File, args []string) *exec.Cmd {
103
-		c.Path = d.initPath
104
-		c.Args = append([]string{
102
+	return namespaces.Exec(container, c.ProcessConfig.Stdin, c.ProcessConfig.Stdout, c.ProcessConfig.Stderr, c.ProcessConfig.Console, c.Rootfs, dataPath, args, func(container *libcontainer.Config, console, rootfs, dataPath, init string, child *os.File, args []string) *exec.Cmd {
103
+		c.ProcessConfig.Path = d.initPath
104
+		c.ProcessConfig.Args = append([]string{
105 105
 			DriverName,
106 106
 			"-console", console,
107 107
 			"-pipe", "3",
... ...
@@ -110,25 +110,25 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
110 110
 		}, args...)
111 111
 
112 112
 		// set this to nil so that when we set the clone flags anything else is reset
113
-		c.SysProcAttr = &syscall.SysProcAttr{
113
+		c.ProcessConfig.SysProcAttr = &syscall.SysProcAttr{
114 114
 			Cloneflags: uintptr(namespaces.GetNamespaceFlags(container.Namespaces)),
115 115
 		}
116
-		c.ExtraFiles = []*os.File{child}
116
+		c.ProcessConfig.ExtraFiles = []*os.File{child}
117 117
 
118
-		c.Env = container.Env
119
-		c.Dir = c.Rootfs
118
+		c.ProcessConfig.Env = container.Env
119
+		c.ProcessConfig.Dir = c.Rootfs
120 120
 
121
-		return &c.Cmd
121
+		return &c.ProcessConfig.Cmd
122 122
 	}, func() {
123 123
 		if startCallback != nil {
124
-			c.ContainerPid = c.Process.Pid
125
-			startCallback(c)
124
+			c.ProcessConfig.ContainerPid = c.ProcessConfig.Process.Pid
125
+			startCallback(&c.ProcessConfig)
126 126
 		}
127 127
 	})
128 128
 }
129 129
 
130 130
 func (d *driver) Kill(p *execdriver.Command, sig int) error {
131
-	return syscall.Kill(p.Process.Pid, syscall.Signal(sig))
131
+	return syscall.Kill(p.ProcessConfig.Process.Pid, syscall.Signal(sig))
132 132
 }
133 133
 
134 134
 func (d *driver) Pause(c *execdriver.Command) error {
... ...
@@ -176,14 +176,14 @@ func (d *driver) Terminate(p *execdriver.Command) error {
176 176
 		state = &libcontainer.State{InitStartTime: string(data)}
177 177
 	}
178 178
 
179
-	currentStartTime, err := system.GetProcessStartTime(p.Process.Pid)
179
+	currentStartTime, err := system.GetProcessStartTime(p.ProcessConfig.Process.Pid)
180 180
 	if err != nil {
181 181
 		return err
182 182
 	}
183 183
 
184 184
 	if state.InitStartTime == currentStartTime {
185
-		err = syscall.Kill(p.Process.Pid, 9)
186
-		syscall.Wait4(p.Process.Pid, nil, 0, nil)
185
+		err = syscall.Kill(p.ProcessConfig.Process.Pid, 9)
186
+		syscall.Wait4(p.ProcessConfig.Process.Pid, nil, 0, nil)
187 187
 	}
188 188
 	d.removeContainerRoot(p.ID)
189 189
 
... ...
@@ -252,7 +252,7 @@ type TtyConsole struct {
252 252
 	MasterPty *os.File
253 253
 }
254 254
 
255
-func NewTtyConsole(command *execdriver.Command, pipes *execdriver.Pipes) (*TtyConsole, error) {
255
+func NewTtyConsole(processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes) (*TtyConsole, error) {
256 256
 	ptyMaster, console, err := consolepkg.CreateMasterAndConsole()
257 257
 	if err != nil {
258 258
 		return nil, err
... ...
@@ -262,12 +262,12 @@ func NewTtyConsole(command *execdriver.Command, pipes *execdriver.Pipes) (*TtyCo
262 262
 		MasterPty: ptyMaster,
263 263
 	}
264 264
 
265
-	if err := tty.AttachPipes(&command.Cmd, pipes); err != nil {
265
+	if err := tty.AttachPipes(&processConfig.Cmd, pipes); err != nil {
266 266
 		tty.Close()
267 267
 		return nil, err
268 268
 	}
269 269
 
270
-	command.Console = console
270
+	processConfig.Console = console
271 271
 
272 272
 	return tty, nil
273 273
 }
... ...
@@ -8,10 +8,10 @@ import (
8 8
 type StdConsole struct {
9 9
 }
10 10
 
11
-func NewStdConsole(command *Command, pipes *Pipes) (*StdConsole, error) {
11
+func NewStdConsole(processConfig *ProcessConfig, pipes *Pipes) (*StdConsole, error) {
12 12
 	std := &StdConsole{}
13 13
 
14
-	if err := std.AttachPipes(&command.Cmd, pipes); err != nil {
14
+	if err := std.AttachPipes(&processConfig.Cmd, pipes); err != nil {
15 15
 		return nil, err
16 16
 	}
17 17
 	return std, nil
... ...
@@ -128,7 +128,7 @@ func (m *containerMonitor) Start() error {
128 128
 			return err
129 129
 		}
130 130
 
131
-		pipes := execdriver.NewPipes(m.container.stdin, m.container.stdout, m.container.stderr, m.container.Config.OpenStdin)
131
+		pipes := execdriver.NewPipes(m.container.StdConfig.stdin, m.container.StdConfig.stdout, m.container.StdConfig.stderr, m.container.Config.OpenStdin)
132 132
 
133 133
 		m.container.LogEvent("start")
134 134
 
... ...
@@ -233,17 +233,17 @@ func (m *containerMonitor) shouldRestart(exitStatus int) bool {
233 233
 
234 234
 // callback ensures that the container's state is properly updated after we
235 235
 // received ack from the execution drivers
236
-func (m *containerMonitor) callback(command *execdriver.Command) {
237
-	if command.Tty {
236
+func (m *containerMonitor) callback(processConfig *execdriver.ProcessConfig) {
237
+	if processConfig.Tty {
238 238
 		// The callback is called after the process Start()
239 239
 		// so we are in the parent process. In TTY mode, stdin/out/err is the PtySlace
240 240
 		// which we close here.
241
-		if c, ok := command.Stdout.(io.Closer); ok {
241
+		if c, ok := processConfig.Stdout.(io.Closer); ok {
242 242
 			c.Close()
243 243
 		}
244 244
 	}
245 245
 
246
-	m.container.State.setRunning(command.Pid())
246
+	m.container.State.setRunning(processConfig.Pid())
247 247
 
248 248
 	// signal that the process has started
249 249
 	// close channel only if not closed
... ...
@@ -269,33 +269,33 @@ func (m *containerMonitor) resetContainer(lock bool) {
269 269
 	}
270 270
 
271 271
 	if container.Config.OpenStdin {
272
-		if err := container.stdin.Close(); err != nil {
272
+		if err := container.StdConfig.stdin.Close(); err != nil {
273 273
 			log.Errorf("%s: Error close stdin: %s", container.ID, err)
274 274
 		}
275 275
 	}
276 276
 
277
-	if err := container.stdout.Clean(); err != nil {
277
+	if err := container.StdConfig.stdout.Clean(); err != nil {
278 278
 		log.Errorf("%s: Error close stdout: %s", container.ID, err)
279 279
 	}
280 280
 
281
-	if err := container.stderr.Clean(); err != nil {
281
+	if err := container.StdConfig.stderr.Clean(); err != nil {
282 282
 		log.Errorf("%s: Error close stderr: %s", container.ID, err)
283 283
 	}
284 284
 
285
-	if container.command != nil && container.command.Terminal != nil {
286
-		if err := container.command.Terminal.Close(); err != nil {
285
+	if container.command != nil && container.command.ProcessConfig.Terminal != nil {
286
+		if err := container.command.ProcessConfig.Terminal.Close(); err != nil {
287 287
 			log.Errorf("%s: Error closing terminal: %s", container.ID, err)
288 288
 		}
289 289
 	}
290 290
 
291 291
 	// Re-create a brand new stdin pipe once the container exited
292 292
 	if container.Config.OpenStdin {
293
-		container.stdin, container.stdinPipe = io.Pipe()
293
+		container.StdConfig.stdin, container.StdConfig.stdinPipe = io.Pipe()
294 294
 	}
295 295
 
296
-	c := container.command.Cmd
296
+	c := container.command.ProcessConfig.Cmd
297 297
 
298
-	container.command.Cmd = exec.Cmd{
298
+	container.command.ProcessConfig.Cmd = exec.Cmd{
299 299
 		Stdin:       c.Stdin,
300 300
 		Stdout:      c.Stdout,
301 301
 		Stderr:      c.Stderr,
... ...
@@ -467,7 +467,7 @@ func TestAttachDisconnect(t *testing.T) {
467 467
 	}
468 468
 
469 469
 	// Try to avoid the timeout in destroy. Best effort, don't check error
470
-	cStdin, _ := container.StdinPipe()
470
+	cStdin, _ := container.StdConfig.StdinPipe()
471 471
 	cStdin.Close()
472 472
 	container.State.WaitStop(-1 * time.Second)
473 473
 }
... ...
@@ -25,11 +25,11 @@ func TestRestartStdin(t *testing.T) {
25 25
 	}
26 26
 	defer daemon.Destroy(container)
27 27
 
28
-	stdin, err := container.StdinPipe()
28
+	stdin, err := container.StdConfig.StdinPipe()
29 29
 	if err != nil {
30 30
 		t.Fatal(err)
31 31
 	}
32
-	stdout, err := container.StdoutPipe()
32
+	stdout, err := container.StdConfig.StdoutPipe()
33 33
 	if err != nil {
34 34
 		t.Fatal(err)
35 35
 	}
... ...
@@ -55,11 +55,11 @@ func TestRestartStdin(t *testing.T) {
55 55
 	}
56 56
 
57 57
 	// Restart and try again
58
-	stdin, err = container.StdinPipe()
58
+	stdin, err = container.StdConfig.StdinPipe()
59 59
 	if err != nil {
60 60
 		t.Fatal(err)
61 61
 	}
62
-	stdout, err = container.StdoutPipe()
62
+	stdout, err = container.StdConfig.StdoutPipe()
63 63
 	if err != nil {
64 64
 		t.Fatal(err)
65 65
 	}
... ...
@@ -101,11 +101,11 @@ func TestStdin(t *testing.T) {
101 101
 	}
102 102
 	defer daemon.Destroy(container)
103 103
 
104
-	stdin, err := container.StdinPipe()
104
+	stdin, err := container.StdConfig.StdinPipe()
105 105
 	if err != nil {
106 106
 		t.Fatal(err)
107 107
 	}
108
-	stdout, err := container.StdoutPipe()
108
+	stdout, err := container.StdConfig.StdoutPipe()
109 109
 	if err != nil {
110 110
 		t.Fatal(err)
111 111
 	}
... ...
@@ -146,11 +146,11 @@ func TestTty(t *testing.T) {
146 146
 	}
147 147
 	defer daemon.Destroy(container)
148 148
 
149
-	stdin, err := container.StdinPipe()
149
+	stdin, err := container.StdConfig.StdinPipe()
150 150
 	if err != nil {
151 151
 		t.Fatal(err)
152 152
 	}
153
-	stdout, err := container.StdoutPipe()
153
+	stdout, err := container.StdConfig.StdoutPipe()
154 154
 	if err != nil {
155 155
 		t.Fatal(err)
156 156
 	}
... ...
@@ -611,7 +611,7 @@ func TestRestore(t *testing.T) {
611 611
 	}
612 612
 
613 613
 	// Simulate a crash/manual quit of dockerd: process dies, states stays 'Running'
614
-	cStdin, _ := container2.StdinPipe()
614
+	cStdin, _ := container2.StdConfig.StdinPipe()
615 615
 	cStdin.Close()
616 616
 	if _, err := container2.State.WaitStop(2 * time.Second); err != nil {
617 617
 		t.Fatal(err)
... ...
@@ -84,11 +84,11 @@ func containerFileExists(eng *engine.Engine, id, dir string, t log.Fataler) bool
84 84
 
85 85
 func containerAttach(eng *engine.Engine, id string, t log.Fataler) (io.WriteCloser, io.ReadCloser) {
86 86
 	c := getContainer(eng, id, t)
87
-	i, err := c.StdinPipe()
87
+	i, err := c.StdConfig.StdinPipe()
88 88
 	if err != nil {
89 89
 		t.Fatal(err)
90 90
 	}
91
-	o, err := c.StdoutPipe()
91
+	o, err := c.StdConfig.StdoutPipe()
92 92
 	if err != nil {
93 93
 		t.Fatal(err)
94 94
 	}
... ...
@@ -289,7 +289,7 @@ func runContainer(eng *engine.Engine, r *daemon.Daemon, args []string, t *testin
289 289
 		return "", err
290 290
 	}
291 291
 	defer r.Destroy(container)
292
-	stdout, err := container.StdoutPipe()
292
+	stdout, err := container.StdConfig.StdoutPipe()
293 293
 	if err != nil {
294 294
 		return "", err
295 295
 	}