Browse code

Windows: Graph driver implementation

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

John Howard authored on 2015/06/12 03:29:29
Showing 30 changed files
... ...
@@ -24,7 +24,6 @@ import (
24 24
 	"github.com/docker/docker/cliconfig"
25 25
 	"github.com/docker/docker/daemon"
26 26
 	"github.com/docker/docker/graph"
27
-	imagepkg "github.com/docker/docker/image"
28 27
 	"github.com/docker/docker/pkg/archive"
29 28
 	"github.com/docker/docker/pkg/chrootarchive"
30 29
 	"github.com/docker/docker/pkg/httputils"
... ...
@@ -229,12 +228,20 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowDecomp
229 229
 	}
230 230
 	defer container.Unmount()
231 231
 
232
+	if err := container.PrepareStorage(); err != nil {
233
+		return err
234
+	}
235
+
232 236
 	for _, ci := range copyInfos {
233 237
 		if err := b.addContext(container, ci.origPath, ci.destPath, ci.decompress); err != nil {
234 238
 			return err
235 239
 		}
236 240
 	}
237 241
 
242
+	if err := container.CleanupStorage(); err != nil {
243
+		return err
244
+	}
245
+
238 246
 	if err := b.commit(container.ID, cmd, fmt.Sprintf("%s %s in %s", cmdName, origPaths, dest)); err != nil {
239 247
 		return err
240 248
 	}
... ...
@@ -455,7 +462,7 @@ func ContainsWildcards(name string) bool {
455 455
 	return false
456 456
 }
457 457
 
458
-func (b *Builder) pullImage(name string) (*imagepkg.Image, error) {
458
+func (b *Builder) pullImage(name string) (*graph.Image, error) {
459 459
 	remote, tag := parsers.ParseRepositoryTag(name)
460 460
 	if tag == "" {
461 461
 		tag = "latest"
... ...
@@ -493,7 +500,7 @@ func (b *Builder) pullImage(name string) (*imagepkg.Image, error) {
493 493
 	return image, nil
494 494
 }
495 495
 
496
-func (b *Builder) processImageFrom(img *imagepkg.Image) error {
496
+func (b *Builder) processImageFrom(img *graph.Image) error {
497 497
 	b.image = img.ID
498 498
 
499 499
 	if img.Config != nil {
... ...
@@ -11,6 +11,7 @@ import (
11 11
 	"strings"
12 12
 
13 13
 	"github.com/docker/docker/pkg/homedir"
14
+	"github.com/docker/docker/pkg/system"
14 15
 )
15 16
 
16 17
 const (
... ...
@@ -177,7 +178,7 @@ func (configFile *ConfigFile) Save() error {
177 177
 		return err
178 178
 	}
179 179
 
180
-	if err := os.MkdirAll(filepath.Dir(configFile.filename), 0700); err != nil {
180
+	if err := system.MkdirAll(filepath.Dir(configFile.filename), 0700); err != nil {
181 181
 		return err
182 182
 	}
183 183
 
... ...
@@ -1,7 +1,7 @@
1 1
 package daemon
2 2
 
3 3
 import (
4
-	"github.com/docker/docker/image"
4
+	"github.com/docker/docker/graph"
5 5
 	"github.com/docker/docker/runconfig"
6 6
 )
7 7
 
... ...
@@ -16,7 +16,7 @@ type ContainerCommitConfig struct {
16 16
 
17 17
 // Commit creates a new filesystem image from the current state of a container.
18 18
 // The image can optionally be tagged into a repository
19
-func (daemon *Daemon) Commit(container *Container, c *ContainerCommitConfig) (*image.Image, error) {
19
+func (daemon *Daemon) Commit(container *Container, c *ContainerCommitConfig) (*graph.Image, error) {
20 20
 	if c.Pause && !container.IsPaused() {
21 21
 		container.Pause()
22 22
 		defer container.Unpause()
... ...
@@ -20,7 +20,7 @@ import (
20 20
 	"github.com/docker/docker/daemon/logger"
21 21
 	"github.com/docker/docker/daemon/logger/jsonfilelog"
22 22
 	"github.com/docker/docker/daemon/network"
23
-	"github.com/docker/docker/image"
23
+	"github.com/docker/docker/graph"
24 24
 	"github.com/docker/docker/pkg/archive"
25 25
 	"github.com/docker/docker/pkg/broadcastwriter"
26 26
 	"github.com/docker/docker/pkg/fileutils"
... ...
@@ -259,6 +259,13 @@ func (container *Container) Start() (err error) {
259 259
 	if err := container.Mount(); err != nil {
260 260
 		return err
261 261
 	}
262
+
263
+	// No-op if non-Windows. Once the container filesystem is mounted,
264
+	// prepare the layer to boot using the Windows driver.
265
+	if err := container.PrepareStorage(); err != nil {
266
+		return err
267
+	}
268
+
262 269
 	if err := container.initializeNetworking(); err != nil {
263 270
 		return err
264 271
 	}
... ...
@@ -350,6 +357,10 @@ func (container *Container) cleanup() {
350 350
 
351 351
 	disableAllActiveLinks(container)
352 352
 
353
+	if err := container.CleanupStorage(); err != nil {
354
+		logrus.Errorf("%v: Failed to cleanup storage: %v", container.ID, err)
355
+	}
356
+
353 357
 	if err := container.Unmount(); err != nil {
354 358
 		logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err)
355 359
 	}
... ...
@@ -573,7 +584,7 @@ func (container *Container) Changes() ([]archive.Change, error) {
573 573
 	return container.changes()
574 574
 }
575 575
 
576
-func (container *Container) GetImage() (*image.Image, error) {
576
+func (container *Container) GetImage() (*graph.Image, error) {
577 577
 	if container.daemon == nil {
578 578
 		return nil, fmt.Errorf("Can't get image of unregistered container")
579 579
 	}
... ...
@@ -666,8 +677,15 @@ func (container *Container) Copy(resource string) (io.ReadCloser, error) {
666 666
 	if err != nil {
667 667
 		return nil, err
668 668
 	}
669
+
670
+	if err := container.PrepareStorage(); err != nil {
671
+		container.Unmount()
672
+		return nil, err
673
+	}
674
+
669 675
 	reader := ioutils.NewReadCloserWrapper(archive, func() error {
670 676
 		err := archive.Close()
677
+		container.CleanupStorage()
671 678
 		container.UnmountVolumes(true)
672 679
 		container.Unmount()
673 680
 		return err
674 681
deleted file mode 100644
... ...
@@ -1,1111 +0,0 @@
1
-// +build linux
2
-
3
-package daemon
4
-
5
-import (
6
-	"fmt"
7
-	"io/ioutil"
8
-	"net"
9
-	"os"
10
-	"path"
11
-	"path/filepath"
12
-	"strconv"
13
-	"strings"
14
-	"syscall"
15
-	"time"
16
-
17
-	"github.com/Sirupsen/logrus"
18
-	"github.com/docker/docker/daemon/execdriver"
19
-	"github.com/docker/docker/daemon/network"
20
-	"github.com/docker/docker/links"
21
-	"github.com/docker/docker/pkg/archive"
22
-	"github.com/docker/docker/pkg/directory"
23
-	"github.com/docker/docker/pkg/ioutils"
24
-	"github.com/docker/docker/pkg/nat"
25
-	"github.com/docker/docker/pkg/stringid"
26
-	"github.com/docker/docker/pkg/ulimit"
27
-	"github.com/docker/docker/runconfig"
28
-	"github.com/docker/docker/utils"
29
-	"github.com/docker/libcontainer/configs"
30
-	"github.com/docker/libcontainer/devices"
31
-	"github.com/docker/libnetwork"
32
-	"github.com/docker/libnetwork/netlabel"
33
-	"github.com/docker/libnetwork/options"
34
-	"github.com/docker/libnetwork/types"
35
-)
36
-
37
-const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
38
-
39
-type Container struct {
40
-	CommonContainer
41
-
42
-	// Fields below here are platform specific.
43
-
44
-	AppArmorProfile string
45
-	activeLinks     map[string]*links.Link
46
-}
47
-
48
-func killProcessDirectly(container *Container) error {
49
-	if _, err := container.WaitStop(10 * time.Second); err != nil {
50
-		// Ensure that we don't kill ourselves
51
-		if pid := container.GetPid(); pid != 0 {
52
-			logrus.Infof("Container %s failed to exit within 10 seconds of kill - trying direct SIGKILL", stringid.TruncateID(container.ID))
53
-			if err := syscall.Kill(pid, 9); err != nil {
54
-				if err != syscall.ESRCH {
55
-					return err
56
-				}
57
-				logrus.Debugf("Cannot kill process (pid=%d) with signal 9: no such process.", pid)
58
-			}
59
-		}
60
-	}
61
-	return nil
62
-}
63
-
64
-func (container *Container) setupLinkedContainers() ([]string, error) {
65
-	var (
66
-		env    []string
67
-		daemon = container.daemon
68
-	)
69
-	children, err := daemon.Children(container.Name)
70
-	if err != nil {
71
-		return nil, err
72
-	}
73
-
74
-	if len(children) > 0 {
75
-		container.activeLinks = make(map[string]*links.Link, len(children))
76
-
77
-		// If we encounter an error make sure that we rollback any network
78
-		// config and iptables changes
79
-		rollback := func() {
80
-			for _, link := range container.activeLinks {
81
-				link.Disable()
82
-			}
83
-			container.activeLinks = nil
84
-		}
85
-
86
-		for linkAlias, child := range children {
87
-			if !child.IsRunning() {
88
-				return nil, fmt.Errorf("Cannot link to a non running container: %s AS %s", child.Name, linkAlias)
89
-			}
90
-
91
-			link, err := links.NewLink(
92
-				container.NetworkSettings.IPAddress,
93
-				child.NetworkSettings.IPAddress,
94
-				linkAlias,
95
-				child.Config.Env,
96
-				child.Config.ExposedPorts,
97
-			)
98
-
99
-			if err != nil {
100
-				rollback()
101
-				return nil, err
102
-			}
103
-
104
-			container.activeLinks[link.Alias()] = link
105
-			if err := link.Enable(); err != nil {
106
-				rollback()
107
-				return nil, err
108
-			}
109
-
110
-			for _, envVar := range link.ToEnv() {
111
-				env = append(env, envVar)
112
-			}
113
-		}
114
-	}
115
-	return env, nil
116
-}
117
-
118
-func (container *Container) createDaemonEnvironment(linkedEnv []string) []string {
119
-	// if a domain name was specified, append it to the hostname (see #7851)
120
-	fullHostname := container.Config.Hostname
121
-	if container.Config.Domainname != "" {
122
-		fullHostname = fmt.Sprintf("%s.%s", fullHostname, container.Config.Domainname)
123
-	}
124
-	// Setup environment
125
-	env := []string{
126
-		"PATH=" + DefaultPathEnv,
127
-		"HOSTNAME=" + fullHostname,
128
-		// Note: we don't set HOME here because it'll get autoset intelligently
129
-		// based on the value of USER inside dockerinit, but only if it isn't
130
-		// set already (ie, that can be overridden by setting HOME via -e or ENV
131
-		// in a Dockerfile).
132
-	}
133
-	if container.Config.Tty {
134
-		env = append(env, "TERM=xterm")
135
-	}
136
-	env = append(env, linkedEnv...)
137
-	// because the env on the container can override certain default values
138
-	// we need to replace the 'env' keys where they match and append anything
139
-	// else.
140
-	env = utils.ReplaceOrAppendEnvValues(env, container.Config.Env)
141
-
142
-	return env
143
-}
144
-
145
-func getDevicesFromPath(deviceMapping runconfig.DeviceMapping) (devs []*configs.Device, err error) {
146
-	device, err := devices.DeviceFromPath(deviceMapping.PathOnHost, deviceMapping.CgroupPermissions)
147
-	// if there was no error, return the device
148
-	if err == nil {
149
-		device.Path = deviceMapping.PathInContainer
150
-		return append(devs, device), nil
151
-	}
152
-
153
-	// if the device is not a device node
154
-	// try to see if it's a directory holding many devices
155
-	if err == devices.ErrNotADevice {
156
-
157
-		// check if it is a directory
158
-		if src, e := os.Stat(deviceMapping.PathOnHost); e == nil && src.IsDir() {
159
-
160
-			// mount the internal devices recursively
161
-			filepath.Walk(deviceMapping.PathOnHost, func(dpath string, f os.FileInfo, e error) error {
162
-				childDevice, e := devices.DeviceFromPath(dpath, deviceMapping.CgroupPermissions)
163
-				if e != nil {
164
-					// ignore the device
165
-					return nil
166
-				}
167
-
168
-				// add the device to userSpecified devices
169
-				childDevice.Path = strings.Replace(dpath, deviceMapping.PathOnHost, deviceMapping.PathInContainer, 1)
170
-				devs = append(devs, childDevice)
171
-
172
-				return nil
173
-			})
174
-		}
175
-	}
176
-
177
-	if len(devs) > 0 {
178
-		return devs, nil
179
-	}
180
-
181
-	return devs, fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
182
-}
183
-
184
-func populateCommand(c *Container, env []string) error {
185
-	var en *execdriver.Network
186
-	if !c.Config.NetworkDisabled {
187
-		en = &execdriver.Network{
188
-			NamespacePath: c.NetworkSettings.SandboxKey,
189
-		}
190
-
191
-		parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
192
-		if parts[0] == "container" {
193
-			nc, err := c.getNetworkedContainer()
194
-			if err != nil {
195
-				return err
196
-			}
197
-			en.ContainerID = nc.ID
198
-		}
199
-	}
200
-
201
-	ipc := &execdriver.Ipc{}
202
-
203
-	if c.hostConfig.IpcMode.IsContainer() {
204
-		ic, err := c.getIpcContainer()
205
-		if err != nil {
206
-			return err
207
-		}
208
-		ipc.ContainerID = ic.ID
209
-	} else {
210
-		ipc.HostIpc = c.hostConfig.IpcMode.IsHost()
211
-	}
212
-
213
-	pid := &execdriver.Pid{}
214
-	pid.HostPid = c.hostConfig.PidMode.IsHost()
215
-
216
-	uts := &execdriver.UTS{
217
-		HostUTS: c.hostConfig.UTSMode.IsHost(),
218
-	}
219
-
220
-	// Build lists of devices allowed and created within the container.
221
-	var userSpecifiedDevices []*configs.Device
222
-	for _, deviceMapping := range c.hostConfig.Devices {
223
-		devs, err := getDevicesFromPath(deviceMapping)
224
-		if err != nil {
225
-			return err
226
-		}
227
-
228
-		userSpecifiedDevices = append(userSpecifiedDevices, devs...)
229
-	}
230
-
231
-	allowedDevices := mergeDevices(configs.DefaultAllowedDevices, userSpecifiedDevices)
232
-
233
-	autoCreatedDevices := mergeDevices(configs.DefaultAutoCreatedDevices, userSpecifiedDevices)
234
-
235
-	// TODO: this can be removed after lxc-conf is fully deprecated
236
-	lxcConfig, err := mergeLxcConfIntoOptions(c.hostConfig)
237
-	if err != nil {
238
-		return err
239
-	}
240
-
241
-	var rlimits []*ulimit.Rlimit
242
-	ulimits := c.hostConfig.Ulimits
243
-
244
-	// Merge ulimits with daemon defaults
245
-	ulIdx := make(map[string]*ulimit.Ulimit)
246
-	for _, ul := range ulimits {
247
-		ulIdx[ul.Name] = ul
248
-	}
249
-	for name, ul := range c.daemon.config.Ulimits {
250
-		if _, exists := ulIdx[name]; !exists {
251
-			ulimits = append(ulimits, ul)
252
-		}
253
-	}
254
-
255
-	for _, limit := range ulimits {
256
-		rl, err := limit.GetRlimit()
257
-		if err != nil {
258
-			return err
259
-		}
260
-		rlimits = append(rlimits, rl)
261
-	}
262
-
263
-	resources := &execdriver.Resources{
264
-		Memory:         c.hostConfig.Memory,
265
-		MemorySwap:     c.hostConfig.MemorySwap,
266
-		CpuShares:      c.hostConfig.CpuShares,
267
-		CpusetCpus:     c.hostConfig.CpusetCpus,
268
-		CpusetMems:     c.hostConfig.CpusetMems,
269
-		CpuPeriod:      c.hostConfig.CpuPeriod,
270
-		CpuQuota:       c.hostConfig.CpuQuota,
271
-		BlkioWeight:    c.hostConfig.BlkioWeight,
272
-		Rlimits:        rlimits,
273
-		OomKillDisable: c.hostConfig.OomKillDisable,
274
-	}
275
-
276
-	processConfig := execdriver.ProcessConfig{
277
-		Privileged: c.hostConfig.Privileged,
278
-		Entrypoint: c.Path,
279
-		Arguments:  c.Args,
280
-		Tty:        c.Config.Tty,
281
-		User:       c.Config.User,
282
-	}
283
-
284
-	processConfig.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
285
-	processConfig.Env = env
286
-
287
-	c.command = &execdriver.Command{
288
-		ID:                 c.ID,
289
-		Rootfs:             c.RootfsPath(),
290
-		ReadonlyRootfs:     c.hostConfig.ReadonlyRootfs,
291
-		InitPath:           "/.dockerinit",
292
-		WorkingDir:         c.Config.WorkingDir,
293
-		Network:            en,
294
-		Ipc:                ipc,
295
-		Pid:                pid,
296
-		UTS:                uts,
297
-		Resources:          resources,
298
-		AllowedDevices:     allowedDevices,
299
-		AutoCreatedDevices: autoCreatedDevices,
300
-		CapAdd:             c.hostConfig.CapAdd.Slice(),
301
-		CapDrop:            c.hostConfig.CapDrop.Slice(),
302
-		ProcessConfig:      processConfig,
303
-		ProcessLabel:       c.GetProcessLabel(),
304
-		MountLabel:         c.GetMountLabel(),
305
-		LxcConfig:          lxcConfig,
306
-		AppArmorProfile:    c.AppArmorProfile,
307
-		CgroupParent:       c.hostConfig.CgroupParent,
308
-	}
309
-
310
-	return nil
311
-}
312
-
313
-func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Device {
314
-	if len(userDevices) == 0 {
315
-		return defaultDevices
316
-	}
317
-
318
-	paths := map[string]*configs.Device{}
319
-	for _, d := range userDevices {
320
-		paths[d.Path] = d
321
-	}
322
-
323
-	var devs []*configs.Device
324
-	for _, d := range defaultDevices {
325
-		if _, defined := paths[d.Path]; !defined {
326
-			devs = append(devs, d)
327
-		}
328
-	}
329
-	return append(devs, userDevices...)
330
-}
331
-
332
-// GetSize, return real size, virtual size
333
-func (container *Container) GetSize() (int64, int64) {
334
-	var (
335
-		sizeRw, sizeRootfs int64
336
-		err                error
337
-		driver             = container.daemon.driver
338
-	)
339
-
340
-	if err := container.Mount(); err != nil {
341
-		logrus.Errorf("Failed to compute size of container rootfs %s: %s", container.ID, err)
342
-		return sizeRw, sizeRootfs
343
-	}
344
-	defer container.Unmount()
345
-
346
-	initID := fmt.Sprintf("%s-init", container.ID)
347
-	sizeRw, err = driver.DiffSize(container.ID, initID)
348
-	if err != nil {
349
-		logrus.Errorf("Driver %s couldn't return diff size of container %s: %s", driver, container.ID, err)
350
-		// FIXME: GetSize should return an error. Not changing it now in case
351
-		// there is a side-effect.
352
-		sizeRw = -1
353
-	}
354
-
355
-	if _, err = os.Stat(container.basefs); err == nil {
356
-		if sizeRootfs, err = directory.Size(container.basefs); err != nil {
357
-			sizeRootfs = -1
358
-		}
359
-	}
360
-	return sizeRw, sizeRootfs
361
-}
362
-
363
-func (container *Container) buildHostnameFile() error {
364
-	hostnamePath, err := container.GetRootResourcePath("hostname")
365
-	if err != nil {
366
-		return err
367
-	}
368
-	container.HostnamePath = hostnamePath
369
-
370
-	if container.Config.Domainname != "" {
371
-		return ioutil.WriteFile(container.HostnamePath, []byte(fmt.Sprintf("%s.%s\n", container.Config.Hostname, container.Config.Domainname)), 0644)
372
-	}
373
-	return ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644)
374
-}
375
-
376
-func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, error) {
377
-	var (
378
-		joinOptions []libnetwork.EndpointOption
379
-		err         error
380
-		dns         []string
381
-		dnsSearch   []string
382
-	)
383
-
384
-	joinOptions = append(joinOptions, libnetwork.JoinOptionHostname(container.Config.Hostname),
385
-		libnetwork.JoinOptionDomainname(container.Config.Domainname))
386
-
387
-	if container.hostConfig.NetworkMode.IsHost() {
388
-		joinOptions = append(joinOptions, libnetwork.JoinOptionUseDefaultSandbox())
389
-	}
390
-
391
-	container.HostsPath, err = container.GetRootResourcePath("hosts")
392
-	if err != nil {
393
-		return nil, err
394
-	}
395
-	joinOptions = append(joinOptions, libnetwork.JoinOptionHostsPath(container.HostsPath))
396
-
397
-	container.ResolvConfPath, err = container.GetRootResourcePath("resolv.conf")
398
-	if err != nil {
399
-		return nil, err
400
-	}
401
-	joinOptions = append(joinOptions, libnetwork.JoinOptionResolvConfPath(container.ResolvConfPath))
402
-
403
-	if len(container.hostConfig.Dns) > 0 {
404
-		dns = container.hostConfig.Dns
405
-	} else if len(container.daemon.config.Dns) > 0 {
406
-		dns = container.daemon.config.Dns
407
-	}
408
-
409
-	for _, d := range dns {
410
-		joinOptions = append(joinOptions, libnetwork.JoinOptionDNS(d))
411
-	}
412
-
413
-	if len(container.hostConfig.DnsSearch) > 0 {
414
-		dnsSearch = container.hostConfig.DnsSearch
415
-	} else if len(container.daemon.config.DnsSearch) > 0 {
416
-		dnsSearch = container.daemon.config.DnsSearch
417
-	}
418
-
419
-	for _, ds := range dnsSearch {
420
-		joinOptions = append(joinOptions, libnetwork.JoinOptionDNSSearch(ds))
421
-	}
422
-
423
-	if container.NetworkSettings.SecondaryIPAddresses != nil {
424
-		name := container.Config.Hostname
425
-		if container.Config.Domainname != "" {
426
-			name = name + "." + container.Config.Domainname
427
-		}
428
-
429
-		for _, a := range container.NetworkSettings.SecondaryIPAddresses {
430
-			joinOptions = append(joinOptions, libnetwork.JoinOptionExtraHost(name, a.Addr))
431
-		}
432
-	}
433
-
434
-	var childEndpoints, parentEndpoints []string
435
-
436
-	children, err := container.daemon.Children(container.Name)
437
-	if err != nil {
438
-		return nil, err
439
-	}
440
-
441
-	for linkAlias, child := range children {
442
-		_, alias := path.Split(linkAlias)
443
-		// allow access to the linked container via the alias, real name, and container hostname
444
-		aliasList := alias + " " + child.Config.Hostname
445
-		// only add the name if alias isn't equal to the name
446
-		if alias != child.Name[1:] {
447
-			aliasList = aliasList + " " + child.Name[1:]
448
-		}
449
-		joinOptions = append(joinOptions, libnetwork.JoinOptionExtraHost(aliasList, child.NetworkSettings.IPAddress))
450
-		if child.NetworkSettings.EndpointID != "" {
451
-			childEndpoints = append(childEndpoints, child.NetworkSettings.EndpointID)
452
-		}
453
-	}
454
-
455
-	for _, extraHost := range container.hostConfig.ExtraHosts {
456
-		// allow IPv6 addresses in extra hosts; only split on first ":"
457
-		parts := strings.SplitN(extraHost, ":", 2)
458
-		joinOptions = append(joinOptions, libnetwork.JoinOptionExtraHost(parts[0], parts[1]))
459
-	}
460
-
461
-	refs := container.daemon.ContainerGraph().RefPaths(container.ID)
462
-	for _, ref := range refs {
463
-		if ref.ParentID == "0" {
464
-			continue
465
-		}
466
-
467
-		c, err := container.daemon.Get(ref.ParentID)
468
-		if err != nil {
469
-			logrus.Error(err)
470
-		}
471
-
472
-		if c != nil && !container.daemon.config.DisableBridge && container.hostConfig.NetworkMode.IsPrivate() {
473
-			logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, container.NetworkSettings.IPAddress)
474
-			joinOptions = append(joinOptions, libnetwork.JoinOptionParentUpdate(c.NetworkSettings.EndpointID, ref.Name, container.NetworkSettings.IPAddress))
475
-			if c.NetworkSettings.EndpointID != "" {
476
-				parentEndpoints = append(parentEndpoints, c.NetworkSettings.EndpointID)
477
-			}
478
-		}
479
-	}
480
-
481
-	linkOptions := options.Generic{
482
-		netlabel.GenericData: options.Generic{
483
-			"ParentEndpoints": parentEndpoints,
484
-			"ChildEndpoints":  childEndpoints,
485
-		},
486
-	}
487
-
488
-	joinOptions = append(joinOptions, libnetwork.JoinOptionGeneric(linkOptions))
489
-
490
-	return joinOptions, nil
491
-}
492
-
493
-func (container *Container) buildPortMapInfo(n libnetwork.Network, ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) {
494
-	if ep == nil {
495
-		return nil, fmt.Errorf("invalid endpoint while building port map info")
496
-	}
497
-
498
-	if networkSettings == nil {
499
-		return nil, fmt.Errorf("invalid networksettings while building port map info")
500
-	}
501
-
502
-	driverInfo, err := ep.DriverInfo()
503
-	if err != nil {
504
-		return nil, err
505
-	}
506
-
507
-	if driverInfo == nil {
508
-		// It is not an error for epInfo to be nil
509
-		return networkSettings, nil
510
-	}
511
-
512
-	if mac, ok := driverInfo[netlabel.MacAddress]; ok {
513
-		networkSettings.MacAddress = mac.(net.HardwareAddr).String()
514
-	}
515
-
516
-	networkSettings.Ports = nat.PortMap{}
517
-
518
-	if expData, ok := driverInfo[netlabel.ExposedPorts]; ok {
519
-		if exposedPorts, ok := expData.([]types.TransportPort); ok {
520
-			for _, tp := range exposedPorts {
521
-				natPort := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port)))
522
-				networkSettings.Ports[natPort] = nil
523
-			}
524
-		}
525
-	}
526
-
527
-	mapData, ok := driverInfo[netlabel.PortMap]
528
-	if !ok {
529
-		return networkSettings, nil
530
-	}
531
-
532
-	if portMapping, ok := mapData.([]types.PortBinding); ok {
533
-		for _, pp := range portMapping {
534
-			natPort := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port)))
535
-			natBndg := nat.PortBinding{HostIp: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))}
536
-			networkSettings.Ports[natPort] = append(networkSettings.Ports[natPort], natBndg)
537
-		}
538
-	}
539
-
540
-	return networkSettings, nil
541
-}
542
-
543
-func (container *Container) buildEndpointInfo(n libnetwork.Network, ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) {
544
-	if ep == nil {
545
-		return nil, fmt.Errorf("invalid endpoint while building port map info")
546
-	}
547
-
548
-	if networkSettings == nil {
549
-		return nil, fmt.Errorf("invalid networksettings while building port map info")
550
-	}
551
-
552
-	epInfo := ep.Info()
553
-	if epInfo == nil {
554
-		// It is not an error to get an empty endpoint info
555
-		return networkSettings, nil
556
-	}
557
-
558
-	ifaceList := epInfo.InterfaceList()
559
-	if len(ifaceList) == 0 {
560
-		return networkSettings, nil
561
-	}
562
-
563
-	iface := ifaceList[0]
564
-
565
-	ones, _ := iface.Address().Mask.Size()
566
-	networkSettings.IPAddress = iface.Address().IP.String()
567
-	networkSettings.IPPrefixLen = ones
568
-
569
-	if iface.AddressIPv6().IP.To16() != nil {
570
-		onesv6, _ := iface.AddressIPv6().Mask.Size()
571
-		networkSettings.GlobalIPv6Address = iface.AddressIPv6().IP.String()
572
-		networkSettings.GlobalIPv6PrefixLen = onesv6
573
-	}
574
-
575
-	if len(ifaceList) == 1 {
576
-		return networkSettings, nil
577
-	}
578
-
579
-	networkSettings.SecondaryIPAddresses = make([]network.Address, 0, len(ifaceList)-1)
580
-	networkSettings.SecondaryIPv6Addresses = make([]network.Address, 0, len(ifaceList)-1)
581
-	for _, iface := range ifaceList[1:] {
582
-		ones, _ := iface.Address().Mask.Size()
583
-		addr := network.Address{Addr: iface.Address().IP.String(), PrefixLen: ones}
584
-		networkSettings.SecondaryIPAddresses = append(networkSettings.SecondaryIPAddresses, addr)
585
-
586
-		if iface.AddressIPv6().IP.To16() != nil {
587
-			onesv6, _ := iface.AddressIPv6().Mask.Size()
588
-			addrv6 := network.Address{Addr: iface.AddressIPv6().IP.String(), PrefixLen: onesv6}
589
-			networkSettings.SecondaryIPv6Addresses = append(networkSettings.SecondaryIPv6Addresses, addrv6)
590
-		}
591
-	}
592
-
593
-	return networkSettings, nil
594
-}
595
-
596
-func (container *Container) updateJoinInfo(ep libnetwork.Endpoint) error {
597
-	epInfo := ep.Info()
598
-	if epInfo == nil {
599
-		// It is not an error to get an empty endpoint info
600
-		return nil
601
-	}
602
-
603
-	container.NetworkSettings.Gateway = epInfo.Gateway().String()
604
-	if epInfo.GatewayIPv6().To16() != nil {
605
-		container.NetworkSettings.IPv6Gateway = epInfo.GatewayIPv6().String()
606
-	}
607
-
608
-	container.NetworkSettings.SandboxKey = epInfo.SandboxKey()
609
-
610
-	return nil
611
-}
612
-
613
-func (container *Container) updateNetworkSettings(n libnetwork.Network, ep libnetwork.Endpoint) error {
614
-	networkSettings := &network.Settings{NetworkID: n.ID(), EndpointID: ep.ID()}
615
-
616
-	networkSettings, err := container.buildPortMapInfo(n, ep, networkSettings)
617
-	if err != nil {
618
-		return err
619
-	}
620
-
621
-	networkSettings, err = container.buildEndpointInfo(n, ep, networkSettings)
622
-	if err != nil {
623
-		return err
624
-	}
625
-
626
-	if container.hostConfig.NetworkMode == runconfig.NetworkMode("bridge") {
627
-		networkSettings.Bridge = container.daemon.config.Bridge.Iface
628
-	}
629
-
630
-	container.NetworkSettings = networkSettings
631
-	return nil
632
-}
633
-
634
-func (container *Container) UpdateNetwork() error {
635
-	n, err := container.daemon.netController.NetworkByID(container.NetworkSettings.NetworkID)
636
-	if err != nil {
637
-		return fmt.Errorf("error locating network id %s: %v", container.NetworkSettings.NetworkID, err)
638
-	}
639
-
640
-	ep, err := n.EndpointByID(container.NetworkSettings.EndpointID)
641
-	if err != nil {
642
-		return fmt.Errorf("error locating endpoint id %s: %v", container.NetworkSettings.EndpointID, err)
643
-	}
644
-
645
-	if err := ep.Leave(container.ID); err != nil {
646
-		return fmt.Errorf("endpoint leave failed: %v", err)
647
-
648
-	}
649
-
650
-	joinOptions, err := container.buildJoinOptions()
651
-	if err != nil {
652
-		return fmt.Errorf("Update network failed: %v", err)
653
-	}
654
-
655
-	if err := ep.Join(container.ID, joinOptions...); err != nil {
656
-		return fmt.Errorf("endpoint join failed: %v", err)
657
-	}
658
-
659
-	if err := container.updateJoinInfo(ep); err != nil {
660
-		return fmt.Errorf("Updating join info failed: %v", err)
661
-	}
662
-
663
-	return nil
664
-}
665
-
666
-func (container *Container) buildCreateEndpointOptions() ([]libnetwork.EndpointOption, error) {
667
-	var (
668
-		portSpecs     = make(nat.PortSet)
669
-		bindings      = make(nat.PortMap)
670
-		pbList        []types.PortBinding
671
-		exposeList    []types.TransportPort
672
-		createOptions []libnetwork.EndpointOption
673
-	)
674
-
675
-	if container.Config.ExposedPorts != nil {
676
-		portSpecs = container.Config.ExposedPorts
677
-	}
678
-
679
-	if container.hostConfig.PortBindings != nil {
680
-		for p, b := range container.hostConfig.PortBindings {
681
-			bindings[p] = []nat.PortBinding{}
682
-			for _, bb := range b {
683
-				bindings[p] = append(bindings[p], nat.PortBinding{
684
-					HostIp:   bb.HostIp,
685
-					HostPort: bb.HostPort,
686
-				})
687
-			}
688
-		}
689
-	}
690
-
691
-	container.NetworkSettings.PortMapping = nil
692
-
693
-	ports := make([]nat.Port, len(portSpecs))
694
-	var i int
695
-	for p := range portSpecs {
696
-		ports[i] = p
697
-		i++
698
-	}
699
-	nat.SortPortMap(ports, bindings)
700
-	for _, port := range ports {
701
-		expose := types.TransportPort{}
702
-		expose.Proto = types.ParseProtocol(port.Proto())
703
-		expose.Port = uint16(port.Int())
704
-		exposeList = append(exposeList, expose)
705
-
706
-		pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto}
707
-		binding := bindings[port]
708
-		for i := 0; i < len(binding); i++ {
709
-			pbCopy := pb.GetCopy()
710
-			pbCopy.HostPort = uint16(nat.Port(binding[i].HostPort).Int())
711
-			pbCopy.HostIP = net.ParseIP(binding[i].HostIp)
712
-			pbList = append(pbList, pbCopy)
713
-		}
714
-
715
-		if container.hostConfig.PublishAllPorts && len(binding) == 0 {
716
-			pbList = append(pbList, pb)
717
-		}
718
-	}
719
-
720
-	createOptions = append(createOptions,
721
-		libnetwork.CreateOptionPortMapping(pbList),
722
-		libnetwork.CreateOptionExposedPorts(exposeList))
723
-
724
-	if container.Config.MacAddress != "" {
725
-		mac, err := net.ParseMAC(container.Config.MacAddress)
726
-		if err != nil {
727
-			return nil, err
728
-		}
729
-
730
-		genericOption := options.Generic{
731
-			netlabel.MacAddress: mac,
732
-		}
733
-
734
-		createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption))
735
-	}
736
-
737
-	return createOptions, nil
738
-}
739
-
740
-func parseService(controller libnetwork.NetworkController, service string) (string, string, string) {
741
-	dn := controller.Config().Daemon.DefaultNetwork
742
-	dd := controller.Config().Daemon.DefaultDriver
743
-
744
-	snd := strings.Split(service, ".")
745
-	if len(snd) > 2 {
746
-		return strings.Join(snd[:len(snd)-2], "."), snd[len(snd)-2], snd[len(snd)-1]
747
-	}
748
-	if len(snd) > 1 {
749
-		return snd[0], snd[1], dd
750
-	}
751
-	return snd[0], dn, dd
752
-}
753
-
754
-func createNetwork(controller libnetwork.NetworkController, dnet string, driver string) (libnetwork.Network, error) {
755
-	createOptions := []libnetwork.NetworkOption{}
756
-	genericOption := options.Generic{}
757
-
758
-	// Bridge driver is special due to legacy reasons
759
-	if runconfig.NetworkMode(driver).IsBridge() {
760
-		genericOption[netlabel.GenericData] = map[string]interface{}{
761
-			"BridgeName":            dnet,
762
-			"AllowNonDefaultBridge": "true",
763
-		}
764
-		networkOption := libnetwork.NetworkOptionGeneric(genericOption)
765
-		createOptions = append(createOptions, networkOption)
766
-	}
767
-
768
-	return controller.NewNetwork(driver, dnet, createOptions...)
769
-}
770
-
771
-func (container *Container) secondaryNetworkRequired(primaryNetworkType string) bool {
772
-	switch primaryNetworkType {
773
-	case "bridge", "none", "host", "container":
774
-		return false
775
-	}
776
-
777
-	if container.daemon.config.DisableBridge {
778
-		return false
779
-	}
780
-
781
-	if container.Config.ExposedPorts != nil && len(container.Config.ExposedPorts) > 0 {
782
-		return true
783
-	}
784
-	if container.hostConfig.PortBindings != nil && len(container.hostConfig.PortBindings) > 0 {
785
-		return true
786
-	}
787
-	return false
788
-}
789
-
790
-func (container *Container) AllocateNetwork() error {
791
-	mode := container.hostConfig.NetworkMode
792
-	controller := container.daemon.netController
793
-	if container.Config.NetworkDisabled || mode.IsContainer() {
794
-		return nil
795
-	}
796
-
797
-	networkDriver := string(mode)
798
-	service := container.Config.PublishService
799
-	networkName := mode.NetworkName()
800
-	if mode.IsDefault() {
801
-		if service != "" {
802
-			service, networkName, networkDriver = parseService(controller, service)
803
-		} else {
804
-			networkName = controller.Config().Daemon.DefaultNetwork
805
-			networkDriver = controller.Config().Daemon.DefaultDriver
806
-		}
807
-	} else if service != "" {
808
-		return fmt.Errorf("conflicting options: publishing a service and network mode")
809
-	}
810
-
811
-	if runconfig.NetworkMode(networkDriver).IsBridge() && container.daemon.config.DisableBridge {
812
-		container.Config.NetworkDisabled = true
813
-		return nil
814
-	}
815
-
816
-	if service == "" {
817
-		// dot character "." has a special meaning to support SERVICE[.NETWORK] format.
818
-		// For backward compatiblity, replacing "." with "-", instead of failing
819
-		service = strings.Replace(container.Name, ".", "-", -1)
820
-		// Service names dont like "/" in them. removing it instead of failing for backward compatibility
821
-		service = strings.Replace(service, "/", "", -1)
822
-	}
823
-
824
-	if container.secondaryNetworkRequired(networkDriver) {
825
-		// Configure Bridge as secondary network for port binding purposes
826
-		if err := container.configureNetwork("bridge", service, "bridge", false); err != nil {
827
-			return err
828
-		}
829
-	}
830
-
831
-	if err := container.configureNetwork(networkName, service, networkDriver, mode.IsDefault()); err != nil {
832
-		return err
833
-	}
834
-
835
-	return container.WriteHostConfig()
836
-}
837
-
838
-func (container *Container) configureNetwork(networkName, service, networkDriver string, canCreateNetwork bool) error {
839
-	controller := container.daemon.netController
840
-	n, err := controller.NetworkByName(networkName)
841
-	if err != nil {
842
-		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok || !canCreateNetwork {
843
-			return err
844
-		}
845
-
846
-		if n, err = createNetwork(controller, networkName, networkDriver); err != nil {
847
-			return err
848
-		}
849
-	}
850
-
851
-	ep, err := n.EndpointByName(service)
852
-	if err != nil {
853
-		if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok {
854
-			return err
855
-		}
856
-
857
-		createOptions, err := container.buildCreateEndpointOptions()
858
-		if err != nil {
859
-			return err
860
-		}
861
-
862
-		ep, err = n.CreateEndpoint(service, createOptions...)
863
-		if err != nil {
864
-			return err
865
-		}
866
-	}
867
-
868
-	if err := container.updateNetworkSettings(n, ep); err != nil {
869
-		return err
870
-	}
871
-
872
-	joinOptions, err := container.buildJoinOptions()
873
-	if err != nil {
874
-		return err
875
-	}
876
-
877
-	if err := ep.Join(container.ID, joinOptions...); err != nil {
878
-		return err
879
-	}
880
-
881
-	if err := container.updateJoinInfo(ep); err != nil {
882
-		return fmt.Errorf("Updating join info failed: %v", err)
883
-	}
884
-
885
-	return nil
886
-}
887
-
888
-func (container *Container) initializeNetworking() error {
889
-	var err error
890
-
891
-	// Make sure NetworkMode has an acceptable value before
892
-	// initializing networking.
893
-	if container.hostConfig.NetworkMode == runconfig.NetworkMode("") {
894
-		container.hostConfig.NetworkMode = runconfig.NetworkMode("default")
895
-	}
896
-	if container.hostConfig.NetworkMode.IsContainer() {
897
-		// we need to get the hosts files from the container to join
898
-		nc, err := container.getNetworkedContainer()
899
-		if err != nil {
900
-			return err
901
-		}
902
-		container.HostnamePath = nc.HostnamePath
903
-		container.HostsPath = nc.HostsPath
904
-		container.ResolvConfPath = nc.ResolvConfPath
905
-		container.Config.Hostname = nc.Config.Hostname
906
-		container.Config.Domainname = nc.Config.Domainname
907
-		return nil
908
-	}
909
-
910
-	if container.hostConfig.NetworkMode.IsHost() {
911
-		container.Config.Hostname, err = os.Hostname()
912
-		if err != nil {
913
-			return err
914
-		}
915
-
916
-		parts := strings.SplitN(container.Config.Hostname, ".", 2)
917
-		if len(parts) > 1 {
918
-			container.Config.Hostname = parts[0]
919
-			container.Config.Domainname = parts[1]
920
-		}
921
-
922
-	}
923
-
924
-	if err := container.AllocateNetwork(); err != nil {
925
-		return err
926
-	}
927
-
928
-	return container.buildHostnameFile()
929
-}
930
-
931
-func (container *Container) ExportRw() (archive.Archive, error) {
932
-	if container.daemon == nil {
933
-		return nil, fmt.Errorf("Can't load storage driver for unregistered container %s", container.ID)
934
-	}
935
-	archive, err := container.daemon.Diff(container)
936
-	if err != nil {
937
-		return nil, err
938
-	}
939
-	return ioutils.NewReadCloserWrapper(archive, func() error {
940
-			err := archive.Close()
941
-			return err
942
-		}),
943
-		nil
944
-}
945
-
946
-func (container *Container) getIpcContainer() (*Container, error) {
947
-	containerID := container.hostConfig.IpcMode.Container()
948
-	c, err := container.daemon.Get(containerID)
949
-	if err != nil {
950
-		return nil, err
951
-	}
952
-	if !c.IsRunning() {
953
-		return nil, fmt.Errorf("cannot join IPC of a non running container: %s", containerID)
954
-	}
955
-	return c, nil
956
-}
957
-
958
-func (container *Container) setupWorkingDirectory() error {
959
-	if container.Config.WorkingDir != "" {
960
-		container.Config.WorkingDir = filepath.Clean(container.Config.WorkingDir)
961
-
962
-		pth, err := container.GetResourcePath(container.Config.WorkingDir)
963
-		if err != nil {
964
-			return err
965
-		}
966
-
967
-		pthInfo, err := os.Stat(pth)
968
-		if err != nil {
969
-			if !os.IsNotExist(err) {
970
-				return err
971
-			}
972
-
973
-			if err := os.MkdirAll(pth, 0755); err != nil {
974
-				return err
975
-			}
976
-		}
977
-		if pthInfo != nil && !pthInfo.IsDir() {
978
-			return fmt.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)
979
-		}
980
-	}
981
-	return nil
982
-}
983
-
984
-func (container *Container) getNetworkedContainer() (*Container, error) {
985
-	parts := strings.SplitN(string(container.hostConfig.NetworkMode), ":", 2)
986
-	switch parts[0] {
987
-	case "container":
988
-		if len(parts) != 2 {
989
-			return nil, fmt.Errorf("no container specified to join network")
990
-		}
991
-		nc, err := container.daemon.Get(parts[1])
992
-		if err != nil {
993
-			return nil, err
994
-		}
995
-		if container == nc {
996
-			return nil, fmt.Errorf("cannot join own network")
997
-		}
998
-		if !nc.IsRunning() {
999
-			return nil, fmt.Errorf("cannot join network of a non running container: %s", parts[1])
1000
-		}
1001
-		return nc, nil
1002
-	default:
1003
-		return nil, fmt.Errorf("network mode not set to container")
1004
-	}
1005
-}
1006
-
1007
-func (container *Container) ReleaseNetwork() {
1008
-	if container.hostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
1009
-		return
1010
-	}
1011
-
1012
-	eid := container.NetworkSettings.EndpointID
1013
-	nid := container.NetworkSettings.NetworkID
1014
-
1015
-	container.NetworkSettings = &network.Settings{}
1016
-
1017
-	if nid == "" || eid == "" {
1018
-		return
1019
-	}
1020
-
1021
-	n, err := container.daemon.netController.NetworkByID(nid)
1022
-	if err != nil {
1023
-		logrus.Errorf("error locating network id %s: %v", nid, err)
1024
-		return
1025
-	}
1026
-
1027
-	ep, err := n.EndpointByID(eid)
1028
-	if err != nil {
1029
-		logrus.Errorf("error locating endpoint id %s: %v", eid, err)
1030
-		return
1031
-	}
1032
-
1033
-	switch {
1034
-	case container.hostConfig.NetworkMode.IsHost():
1035
-		if err := ep.Leave(container.ID); err != nil {
1036
-			logrus.Errorf("Error leaving endpoint id %s for container %s: %v", eid, container.ID, err)
1037
-			return
1038
-		}
1039
-	default:
1040
-		if err := container.daemon.netController.LeaveAll(container.ID); err != nil {
1041
-			logrus.Errorf("Leave all failed for  %s: %v", container.ID, err)
1042
-			return
1043
-		}
1044
-	}
1045
-
1046
-	// In addition to leaving all endpoints, delete implicitly created endpoint
1047
-	if container.Config.PublishService == "" {
1048
-		if err := ep.Delete(); err != nil {
1049
-			logrus.Errorf("deleting endpoint failed: %v", err)
1050
-		}
1051
-	}
1052
-
1053
-}
1054
-
1055
-func disableAllActiveLinks(container *Container) {
1056
-	if container.activeLinks != nil {
1057
-		for _, link := range container.activeLinks {
1058
-			link.Disable()
1059
-		}
1060
-	}
1061
-}
1062
-
1063
-func (container *Container) DisableLink(name string) {
1064
-	if container.activeLinks != nil {
1065
-		if link, exists := container.activeLinks[name]; exists {
1066
-			link.Disable()
1067
-			delete(container.activeLinks, name)
1068
-			if err := container.UpdateNetwork(); err != nil {
1069
-				logrus.Debugf("Could not update network to remove link: %v", err)
1070
-			}
1071
-		} else {
1072
-			logrus.Debugf("Could not find active link for %s", name)
1073
-		}
1074
-	}
1075
-}
1076
-
1077
-func (container *Container) UnmountVolumes(forceSyscall bool) error {
1078
-	var volumeMounts []mountPoint
1079
-
1080
-	for _, mntPoint := range container.MountPoints {
1081
-		dest, err := container.GetResourcePath(mntPoint.Destination)
1082
-		if err != nil {
1083
-			return err
1084
-		}
1085
-
1086
-		volumeMounts = append(volumeMounts, mountPoint{Destination: dest, Volume: mntPoint.Volume})
1087
-	}
1088
-
1089
-	for _, mnt := range container.networkMounts() {
1090
-		dest, err := container.GetResourcePath(mnt.Destination)
1091
-		if err != nil {
1092
-			return err
1093
-		}
1094
-
1095
-		volumeMounts = append(volumeMounts, mountPoint{Destination: dest})
1096
-	}
1097
-
1098
-	for _, volumeMount := range volumeMounts {
1099
-		if forceSyscall {
1100
-			syscall.Unmount(volumeMount.Destination, 0)
1101
-		}
1102
-
1103
-		if volumeMount.Volume != nil {
1104
-			if err := volumeMount.Volume.Unmount(); err != nil {
1105
-				return err
1106
-			}
1107
-		}
1108
-	}
1109
-
1110
-	return nil
1111
-}
1112 1
new file mode 100644
... ...
@@ -0,0 +1,1120 @@
0
+// +build !windows
1
+
2
+package daemon
3
+
4
+import (
5
+	"fmt"
6
+	"io/ioutil"
7
+	"net"
8
+	"os"
9
+	"path"
10
+	"path/filepath"
11
+	"strconv"
12
+	"strings"
13
+	"syscall"
14
+	"time"
15
+
16
+	"github.com/Sirupsen/logrus"
17
+	"github.com/docker/docker/daemon/execdriver"
18
+	"github.com/docker/docker/daemon/network"
19
+	"github.com/docker/docker/links"
20
+	"github.com/docker/docker/pkg/archive"
21
+	"github.com/docker/docker/pkg/directory"
22
+	"github.com/docker/docker/pkg/ioutils"
23
+	"github.com/docker/docker/pkg/nat"
24
+	"github.com/docker/docker/pkg/stringid"
25
+	"github.com/docker/docker/pkg/system"
26
+	"github.com/docker/docker/pkg/ulimit"
27
+	"github.com/docker/docker/runconfig"
28
+	"github.com/docker/docker/utils"
29
+	"github.com/docker/libcontainer/configs"
30
+	"github.com/docker/libcontainer/devices"
31
+	"github.com/docker/libnetwork"
32
+	"github.com/docker/libnetwork/netlabel"
33
+	"github.com/docker/libnetwork/options"
34
+	"github.com/docker/libnetwork/types"
35
+)
36
+
37
+const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
38
+
39
+type Container struct {
40
+	CommonContainer
41
+
42
+	// Fields below here are platform specific.
43
+
44
+	AppArmorProfile string
45
+	activeLinks     map[string]*links.Link
46
+}
47
+
48
+func killProcessDirectly(container *Container) error {
49
+	if _, err := container.WaitStop(10 * time.Second); err != nil {
50
+		// Ensure that we don't kill ourselves
51
+		if pid := container.GetPid(); pid != 0 {
52
+			logrus.Infof("Container %s failed to exit within 10 seconds of kill - trying direct SIGKILL", stringid.TruncateID(container.ID))
53
+			if err := syscall.Kill(pid, 9); err != nil {
54
+				if err != syscall.ESRCH {
55
+					return err
56
+				}
57
+				logrus.Debugf("Cannot kill process (pid=%d) with signal 9: no such process.", pid)
58
+			}
59
+		}
60
+	}
61
+	return nil
62
+}
63
+
64
+func (container *Container) setupLinkedContainers() ([]string, error) {
65
+	var (
66
+		env    []string
67
+		daemon = container.daemon
68
+	)
69
+	children, err := daemon.Children(container.Name)
70
+	if err != nil {
71
+		return nil, err
72
+	}
73
+
74
+	if len(children) > 0 {
75
+		container.activeLinks = make(map[string]*links.Link, len(children))
76
+
77
+		// If we encounter an error make sure that we rollback any network
78
+		// config and iptables changes
79
+		rollback := func() {
80
+			for _, link := range container.activeLinks {
81
+				link.Disable()
82
+			}
83
+			container.activeLinks = nil
84
+		}
85
+
86
+		for linkAlias, child := range children {
87
+			if !child.IsRunning() {
88
+				return nil, fmt.Errorf("Cannot link to a non running container: %s AS %s", child.Name, linkAlias)
89
+			}
90
+
91
+			link, err := links.NewLink(
92
+				container.NetworkSettings.IPAddress,
93
+				child.NetworkSettings.IPAddress,
94
+				linkAlias,
95
+				child.Config.Env,
96
+				child.Config.ExposedPorts,
97
+			)
98
+
99
+			if err != nil {
100
+				rollback()
101
+				return nil, err
102
+			}
103
+
104
+			container.activeLinks[link.Alias()] = link
105
+			if err := link.Enable(); err != nil {
106
+				rollback()
107
+				return nil, err
108
+			}
109
+
110
+			for _, envVar := range link.ToEnv() {
111
+				env = append(env, envVar)
112
+			}
113
+		}
114
+	}
115
+	return env, nil
116
+}
117
+
118
+func (container *Container) createDaemonEnvironment(linkedEnv []string) []string {
119
+	// if a domain name was specified, append it to the hostname (see #7851)
120
+	fullHostname := container.Config.Hostname
121
+	if container.Config.Domainname != "" {
122
+		fullHostname = fmt.Sprintf("%s.%s", fullHostname, container.Config.Domainname)
123
+	}
124
+	// Setup environment
125
+	env := []string{
126
+		"PATH=" + DefaultPathEnv,
127
+		"HOSTNAME=" + fullHostname,
128
+		// Note: we don't set HOME here because it'll get autoset intelligently
129
+		// based on the value of USER inside dockerinit, but only if it isn't
130
+		// set already (ie, that can be overridden by setting HOME via -e or ENV
131
+		// in a Dockerfile).
132
+	}
133
+	if container.Config.Tty {
134
+		env = append(env, "TERM=xterm")
135
+	}
136
+	env = append(env, linkedEnv...)
137
+	// because the env on the container can override certain default values
138
+	// we need to replace the 'env' keys where they match and append anything
139
+	// else.
140
+	env = utils.ReplaceOrAppendEnvValues(env, container.Config.Env)
141
+
142
+	return env
143
+}
144
+
145
+func getDevicesFromPath(deviceMapping runconfig.DeviceMapping) (devs []*configs.Device, err error) {
146
+	device, err := devices.DeviceFromPath(deviceMapping.PathOnHost, deviceMapping.CgroupPermissions)
147
+	// if there was no error, return the device
148
+	if err == nil {
149
+		device.Path = deviceMapping.PathInContainer
150
+		return append(devs, device), nil
151
+	}
152
+
153
+	// if the device is not a device node
154
+	// try to see if it's a directory holding many devices
155
+	if err == devices.ErrNotADevice {
156
+
157
+		// check if it is a directory
158
+		if src, e := os.Stat(deviceMapping.PathOnHost); e == nil && src.IsDir() {
159
+
160
+			// mount the internal devices recursively
161
+			filepath.Walk(deviceMapping.PathOnHost, func(dpath string, f os.FileInfo, e error) error {
162
+				childDevice, e := devices.DeviceFromPath(dpath, deviceMapping.CgroupPermissions)
163
+				if e != nil {
164
+					// ignore the device
165
+					return nil
166
+				}
167
+
168
+				// add the device to userSpecified devices
169
+				childDevice.Path = strings.Replace(dpath, deviceMapping.PathOnHost, deviceMapping.PathInContainer, 1)
170
+				devs = append(devs, childDevice)
171
+
172
+				return nil
173
+			})
174
+		}
175
+	}
176
+
177
+	if len(devs) > 0 {
178
+		return devs, nil
179
+	}
180
+
181
+	return devs, fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
182
+}
183
+
184
+func populateCommand(c *Container, env []string) error {
185
+	var en *execdriver.Network
186
+	if !c.Config.NetworkDisabled {
187
+		en = &execdriver.Network{
188
+			NamespacePath: c.NetworkSettings.SandboxKey,
189
+		}
190
+
191
+		parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
192
+		if parts[0] == "container" {
193
+			nc, err := c.getNetworkedContainer()
194
+			if err != nil {
195
+				return err
196
+			}
197
+			en.ContainerID = nc.ID
198
+		}
199
+	}
200
+
201
+	ipc := &execdriver.Ipc{}
202
+
203
+	if c.hostConfig.IpcMode.IsContainer() {
204
+		ic, err := c.getIpcContainer()
205
+		if err != nil {
206
+			return err
207
+		}
208
+		ipc.ContainerID = ic.ID
209
+	} else {
210
+		ipc.HostIpc = c.hostConfig.IpcMode.IsHost()
211
+	}
212
+
213
+	pid := &execdriver.Pid{}
214
+	pid.HostPid = c.hostConfig.PidMode.IsHost()
215
+
216
+	uts := &execdriver.UTS{
217
+		HostUTS: c.hostConfig.UTSMode.IsHost(),
218
+	}
219
+
220
+	// Build lists of devices allowed and created within the container.
221
+	var userSpecifiedDevices []*configs.Device
222
+	for _, deviceMapping := range c.hostConfig.Devices {
223
+		devs, err := getDevicesFromPath(deviceMapping)
224
+		if err != nil {
225
+			return err
226
+		}
227
+
228
+		userSpecifiedDevices = append(userSpecifiedDevices, devs...)
229
+	}
230
+
231
+	allowedDevices := mergeDevices(configs.DefaultAllowedDevices, userSpecifiedDevices)
232
+
233
+	autoCreatedDevices := mergeDevices(configs.DefaultAutoCreatedDevices, userSpecifiedDevices)
234
+
235
+	// TODO: this can be removed after lxc-conf is fully deprecated
236
+	lxcConfig, err := mergeLxcConfIntoOptions(c.hostConfig)
237
+	if err != nil {
238
+		return err
239
+	}
240
+
241
+	var rlimits []*ulimit.Rlimit
242
+	ulimits := c.hostConfig.Ulimits
243
+
244
+	// Merge ulimits with daemon defaults
245
+	ulIdx := make(map[string]*ulimit.Ulimit)
246
+	for _, ul := range ulimits {
247
+		ulIdx[ul.Name] = ul
248
+	}
249
+	for name, ul := range c.daemon.config.Ulimits {
250
+		if _, exists := ulIdx[name]; !exists {
251
+			ulimits = append(ulimits, ul)
252
+		}
253
+	}
254
+
255
+	for _, limit := range ulimits {
256
+		rl, err := limit.GetRlimit()
257
+		if err != nil {
258
+			return err
259
+		}
260
+		rlimits = append(rlimits, rl)
261
+	}
262
+
263
+	resources := &execdriver.Resources{
264
+		Memory:         c.hostConfig.Memory,
265
+		MemorySwap:     c.hostConfig.MemorySwap,
266
+		CpuShares:      c.hostConfig.CpuShares,
267
+		CpusetCpus:     c.hostConfig.CpusetCpus,
268
+		CpusetMems:     c.hostConfig.CpusetMems,
269
+		CpuPeriod:      c.hostConfig.CpuPeriod,
270
+		CpuQuota:       c.hostConfig.CpuQuota,
271
+		BlkioWeight:    c.hostConfig.BlkioWeight,
272
+		Rlimits:        rlimits,
273
+		OomKillDisable: c.hostConfig.OomKillDisable,
274
+	}
275
+
276
+	processConfig := execdriver.ProcessConfig{
277
+		Privileged: c.hostConfig.Privileged,
278
+		Entrypoint: c.Path,
279
+		Arguments:  c.Args,
280
+		Tty:        c.Config.Tty,
281
+		User:       c.Config.User,
282
+	}
283
+
284
+	processConfig.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
285
+	processConfig.Env = env
286
+
287
+	c.command = &execdriver.Command{
288
+		ID:                 c.ID,
289
+		Rootfs:             c.RootfsPath(),
290
+		ReadonlyRootfs:     c.hostConfig.ReadonlyRootfs,
291
+		InitPath:           "/.dockerinit",
292
+		WorkingDir:         c.Config.WorkingDir,
293
+		Network:            en,
294
+		Ipc:                ipc,
295
+		Pid:                pid,
296
+		UTS:                uts,
297
+		Resources:          resources,
298
+		AllowedDevices:     allowedDevices,
299
+		AutoCreatedDevices: autoCreatedDevices,
300
+		CapAdd:             c.hostConfig.CapAdd.Slice(),
301
+		CapDrop:            c.hostConfig.CapDrop.Slice(),
302
+		ProcessConfig:      processConfig,
303
+		ProcessLabel:       c.GetProcessLabel(),
304
+		MountLabel:         c.GetMountLabel(),
305
+		LxcConfig:          lxcConfig,
306
+		AppArmorProfile:    c.AppArmorProfile,
307
+		CgroupParent:       c.hostConfig.CgroupParent,
308
+	}
309
+
310
+	return nil
311
+}
312
+
313
+func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Device {
314
+	if len(userDevices) == 0 {
315
+		return defaultDevices
316
+	}
317
+
318
+	paths := map[string]*configs.Device{}
319
+	for _, d := range userDevices {
320
+		paths[d.Path] = d
321
+	}
322
+
323
+	var devs []*configs.Device
324
+	for _, d := range defaultDevices {
325
+		if _, defined := paths[d.Path]; !defined {
326
+			devs = append(devs, d)
327
+		}
328
+	}
329
+	return append(devs, userDevices...)
330
+}
331
+
332
+// GetSize, return real size, virtual size
333
+func (container *Container) GetSize() (int64, int64) {
334
+	var (
335
+		sizeRw, sizeRootfs int64
336
+		err                error
337
+		driver             = container.daemon.driver
338
+	)
339
+
340
+	if err := container.Mount(); err != nil {
341
+		logrus.Errorf("Failed to compute size of container rootfs %s: %s", container.ID, err)
342
+		return sizeRw, sizeRootfs
343
+	}
344
+	defer container.Unmount()
345
+
346
+	initID := fmt.Sprintf("%s-init", container.ID)
347
+	sizeRw, err = driver.DiffSize(container.ID, initID)
348
+	if err != nil {
349
+		logrus.Errorf("Driver %s couldn't return diff size of container %s: %s", driver, container.ID, err)
350
+		// FIXME: GetSize should return an error. Not changing it now in case
351
+		// there is a side-effect.
352
+		sizeRw = -1
353
+	}
354
+
355
+	if _, err = os.Stat(container.basefs); err == nil {
356
+		if sizeRootfs, err = directory.Size(container.basefs); err != nil {
357
+			sizeRootfs = -1
358
+		}
359
+	}
360
+	return sizeRw, sizeRootfs
361
+}
362
+
363
+func (container *Container) buildHostnameFile() error {
364
+	hostnamePath, err := container.GetRootResourcePath("hostname")
365
+	if err != nil {
366
+		return err
367
+	}
368
+	container.HostnamePath = hostnamePath
369
+
370
+	if container.Config.Domainname != "" {
371
+		return ioutil.WriteFile(container.HostnamePath, []byte(fmt.Sprintf("%s.%s\n", container.Config.Hostname, container.Config.Domainname)), 0644)
372
+	}
373
+	return ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644)
374
+}
375
+
376
+func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, error) {
377
+	var (
378
+		joinOptions []libnetwork.EndpointOption
379
+		err         error
380
+		dns         []string
381
+		dnsSearch   []string
382
+	)
383
+
384
+	joinOptions = append(joinOptions, libnetwork.JoinOptionHostname(container.Config.Hostname),
385
+		libnetwork.JoinOptionDomainname(container.Config.Domainname))
386
+
387
+	if container.hostConfig.NetworkMode.IsHost() {
388
+		joinOptions = append(joinOptions, libnetwork.JoinOptionUseDefaultSandbox())
389
+	}
390
+
391
+	container.HostsPath, err = container.GetRootResourcePath("hosts")
392
+	if err != nil {
393
+		return nil, err
394
+	}
395
+	joinOptions = append(joinOptions, libnetwork.JoinOptionHostsPath(container.HostsPath))
396
+
397
+	container.ResolvConfPath, err = container.GetRootResourcePath("resolv.conf")
398
+	if err != nil {
399
+		return nil, err
400
+	}
401
+	joinOptions = append(joinOptions, libnetwork.JoinOptionResolvConfPath(container.ResolvConfPath))
402
+
403
+	if len(container.hostConfig.Dns) > 0 {
404
+		dns = container.hostConfig.Dns
405
+	} else if len(container.daemon.config.Dns) > 0 {
406
+		dns = container.daemon.config.Dns
407
+	}
408
+
409
+	for _, d := range dns {
410
+		joinOptions = append(joinOptions, libnetwork.JoinOptionDNS(d))
411
+	}
412
+
413
+	if len(container.hostConfig.DnsSearch) > 0 {
414
+		dnsSearch = container.hostConfig.DnsSearch
415
+	} else if len(container.daemon.config.DnsSearch) > 0 {
416
+		dnsSearch = container.daemon.config.DnsSearch
417
+	}
418
+
419
+	for _, ds := range dnsSearch {
420
+		joinOptions = append(joinOptions, libnetwork.JoinOptionDNSSearch(ds))
421
+	}
422
+
423
+	if container.NetworkSettings.SecondaryIPAddresses != nil {
424
+		name := container.Config.Hostname
425
+		if container.Config.Domainname != "" {
426
+			name = name + "." + container.Config.Domainname
427
+		}
428
+
429
+		for _, a := range container.NetworkSettings.SecondaryIPAddresses {
430
+			joinOptions = append(joinOptions, libnetwork.JoinOptionExtraHost(name, a.Addr))
431
+		}
432
+	}
433
+
434
+	var childEndpoints, parentEndpoints []string
435
+
436
+	children, err := container.daemon.Children(container.Name)
437
+	if err != nil {
438
+		return nil, err
439
+	}
440
+
441
+	for linkAlias, child := range children {
442
+		_, alias := path.Split(linkAlias)
443
+		// allow access to the linked container via the alias, real name, and container hostname
444
+		aliasList := alias + " " + child.Config.Hostname
445
+		// only add the name if alias isn't equal to the name
446
+		if alias != child.Name[1:] {
447
+			aliasList = aliasList + " " + child.Name[1:]
448
+		}
449
+		joinOptions = append(joinOptions, libnetwork.JoinOptionExtraHost(aliasList, child.NetworkSettings.IPAddress))
450
+		if child.NetworkSettings.EndpointID != "" {
451
+			childEndpoints = append(childEndpoints, child.NetworkSettings.EndpointID)
452
+		}
453
+	}
454
+
455
+	for _, extraHost := range container.hostConfig.ExtraHosts {
456
+		// allow IPv6 addresses in extra hosts; only split on first ":"
457
+		parts := strings.SplitN(extraHost, ":", 2)
458
+		joinOptions = append(joinOptions, libnetwork.JoinOptionExtraHost(parts[0], parts[1]))
459
+	}
460
+
461
+	refs := container.daemon.ContainerGraph().RefPaths(container.ID)
462
+	for _, ref := range refs {
463
+		if ref.ParentID == "0" {
464
+			continue
465
+		}
466
+
467
+		c, err := container.daemon.Get(ref.ParentID)
468
+		if err != nil {
469
+			logrus.Error(err)
470
+		}
471
+
472
+		if c != nil && !container.daemon.config.DisableBridge && container.hostConfig.NetworkMode.IsPrivate() {
473
+			logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, container.NetworkSettings.IPAddress)
474
+			joinOptions = append(joinOptions, libnetwork.JoinOptionParentUpdate(c.NetworkSettings.EndpointID, ref.Name, container.NetworkSettings.IPAddress))
475
+			if c.NetworkSettings.EndpointID != "" {
476
+				parentEndpoints = append(parentEndpoints, c.NetworkSettings.EndpointID)
477
+			}
478
+		}
479
+	}
480
+
481
+	linkOptions := options.Generic{
482
+		netlabel.GenericData: options.Generic{
483
+			"ParentEndpoints": parentEndpoints,
484
+			"ChildEndpoints":  childEndpoints,
485
+		},
486
+	}
487
+
488
+	joinOptions = append(joinOptions, libnetwork.JoinOptionGeneric(linkOptions))
489
+
490
+	return joinOptions, nil
491
+}
492
+
493
+func (container *Container) buildPortMapInfo(n libnetwork.Network, ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) {
494
+	if ep == nil {
495
+		return nil, fmt.Errorf("invalid endpoint while building port map info")
496
+	}
497
+
498
+	if networkSettings == nil {
499
+		return nil, fmt.Errorf("invalid networksettings while building port map info")
500
+	}
501
+
502
+	driverInfo, err := ep.DriverInfo()
503
+	if err != nil {
504
+		return nil, err
505
+	}
506
+
507
+	if driverInfo == nil {
508
+		// It is not an error for epInfo to be nil
509
+		return networkSettings, nil
510
+	}
511
+
512
+	if mac, ok := driverInfo[netlabel.MacAddress]; ok {
513
+		networkSettings.MacAddress = mac.(net.HardwareAddr).String()
514
+	}
515
+
516
+	networkSettings.Ports = nat.PortMap{}
517
+
518
+	if expData, ok := driverInfo[netlabel.ExposedPorts]; ok {
519
+		if exposedPorts, ok := expData.([]types.TransportPort); ok {
520
+			for _, tp := range exposedPorts {
521
+				natPort := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port)))
522
+				networkSettings.Ports[natPort] = nil
523
+			}
524
+		}
525
+	}
526
+
527
+	mapData, ok := driverInfo[netlabel.PortMap]
528
+	if !ok {
529
+		return networkSettings, nil
530
+	}
531
+
532
+	if portMapping, ok := mapData.([]types.PortBinding); ok {
533
+		for _, pp := range portMapping {
534
+			natPort := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port)))
535
+			natBndg := nat.PortBinding{HostIp: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))}
536
+			networkSettings.Ports[natPort] = append(networkSettings.Ports[natPort], natBndg)
537
+		}
538
+	}
539
+
540
+	return networkSettings, nil
541
+}
542
+
543
+func (container *Container) buildEndpointInfo(n libnetwork.Network, ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) {
544
+	if ep == nil {
545
+		return nil, fmt.Errorf("invalid endpoint while building port map info")
546
+	}
547
+
548
+	if networkSettings == nil {
549
+		return nil, fmt.Errorf("invalid networksettings while building port map info")
550
+	}
551
+
552
+	epInfo := ep.Info()
553
+	if epInfo == nil {
554
+		// It is not an error to get an empty endpoint info
555
+		return networkSettings, nil
556
+	}
557
+
558
+	ifaceList := epInfo.InterfaceList()
559
+	if len(ifaceList) == 0 {
560
+		return networkSettings, nil
561
+	}
562
+
563
+	iface := ifaceList[0]
564
+
565
+	ones, _ := iface.Address().Mask.Size()
566
+	networkSettings.IPAddress = iface.Address().IP.String()
567
+	networkSettings.IPPrefixLen = ones
568
+
569
+	if iface.AddressIPv6().IP.To16() != nil {
570
+		onesv6, _ := iface.AddressIPv6().Mask.Size()
571
+		networkSettings.GlobalIPv6Address = iface.AddressIPv6().IP.String()
572
+		networkSettings.GlobalIPv6PrefixLen = onesv6
573
+	}
574
+
575
+	if len(ifaceList) == 1 {
576
+		return networkSettings, nil
577
+	}
578
+
579
+	networkSettings.SecondaryIPAddresses = make([]network.Address, 0, len(ifaceList)-1)
580
+	networkSettings.SecondaryIPv6Addresses = make([]network.Address, 0, len(ifaceList)-1)
581
+	for _, iface := range ifaceList[1:] {
582
+		ones, _ := iface.Address().Mask.Size()
583
+		addr := network.Address{Addr: iface.Address().IP.String(), PrefixLen: ones}
584
+		networkSettings.SecondaryIPAddresses = append(networkSettings.SecondaryIPAddresses, addr)
585
+
586
+		if iface.AddressIPv6().IP.To16() != nil {
587
+			onesv6, _ := iface.AddressIPv6().Mask.Size()
588
+			addrv6 := network.Address{Addr: iface.AddressIPv6().IP.String(), PrefixLen: onesv6}
589
+			networkSettings.SecondaryIPv6Addresses = append(networkSettings.SecondaryIPv6Addresses, addrv6)
590
+		}
591
+	}
592
+
593
+	return networkSettings, nil
594
+}
595
+
596
+func (container *Container) updateJoinInfo(ep libnetwork.Endpoint) error {
597
+	epInfo := ep.Info()
598
+	if epInfo == nil {
599
+		// It is not an error to get an empty endpoint info
600
+		return nil
601
+	}
602
+
603
+	container.NetworkSettings.Gateway = epInfo.Gateway().String()
604
+	if epInfo.GatewayIPv6().To16() != nil {
605
+		container.NetworkSettings.IPv6Gateway = epInfo.GatewayIPv6().String()
606
+	}
607
+
608
+	container.NetworkSettings.SandboxKey = epInfo.SandboxKey()
609
+
610
+	return nil
611
+}
612
+
613
+func (container *Container) updateNetworkSettings(n libnetwork.Network, ep libnetwork.Endpoint) error {
614
+	networkSettings := &network.Settings{NetworkID: n.ID(), EndpointID: ep.ID()}
615
+
616
+	networkSettings, err := container.buildPortMapInfo(n, ep, networkSettings)
617
+	if err != nil {
618
+		return err
619
+	}
620
+
621
+	networkSettings, err = container.buildEndpointInfo(n, ep, networkSettings)
622
+	if err != nil {
623
+		return err
624
+	}
625
+
626
+	if container.hostConfig.NetworkMode == runconfig.NetworkMode("bridge") {
627
+		networkSettings.Bridge = container.daemon.config.Bridge.Iface
628
+	}
629
+
630
+	container.NetworkSettings = networkSettings
631
+	return nil
632
+}
633
+
634
+func (container *Container) UpdateNetwork() error {
635
+	n, err := container.daemon.netController.NetworkByID(container.NetworkSettings.NetworkID)
636
+	if err != nil {
637
+		return fmt.Errorf("error locating network id %s: %v", container.NetworkSettings.NetworkID, err)
638
+	}
639
+
640
+	ep, err := n.EndpointByID(container.NetworkSettings.EndpointID)
641
+	if err != nil {
642
+		return fmt.Errorf("error locating endpoint id %s: %v", container.NetworkSettings.EndpointID, err)
643
+	}
644
+
645
+	if err := ep.Leave(container.ID); err != nil {
646
+		return fmt.Errorf("endpoint leave failed: %v", err)
647
+
648
+	}
649
+
650
+	joinOptions, err := container.buildJoinOptions()
651
+	if err != nil {
652
+		return fmt.Errorf("Update network failed: %v", err)
653
+	}
654
+
655
+	if err := ep.Join(container.ID, joinOptions...); err != nil {
656
+		return fmt.Errorf("endpoint join failed: %v", err)
657
+	}
658
+
659
+	if err := container.updateJoinInfo(ep); err != nil {
660
+		return fmt.Errorf("Updating join info failed: %v", err)
661
+	}
662
+
663
+	return nil
664
+}
665
+
666
+func (container *Container) buildCreateEndpointOptions() ([]libnetwork.EndpointOption, error) {
667
+	var (
668
+		portSpecs     = make(nat.PortSet)
669
+		bindings      = make(nat.PortMap)
670
+		pbList        []types.PortBinding
671
+		exposeList    []types.TransportPort
672
+		createOptions []libnetwork.EndpointOption
673
+	)
674
+
675
+	if container.Config.ExposedPorts != nil {
676
+		portSpecs = container.Config.ExposedPorts
677
+	}
678
+
679
+	if container.hostConfig.PortBindings != nil {
680
+		for p, b := range container.hostConfig.PortBindings {
681
+			bindings[p] = []nat.PortBinding{}
682
+			for _, bb := range b {
683
+				bindings[p] = append(bindings[p], nat.PortBinding{
684
+					HostIp:   bb.HostIp,
685
+					HostPort: bb.HostPort,
686
+				})
687
+			}
688
+		}
689
+	}
690
+
691
+	container.NetworkSettings.PortMapping = nil
692
+
693
+	ports := make([]nat.Port, len(portSpecs))
694
+	var i int
695
+	for p := range portSpecs {
696
+		ports[i] = p
697
+		i++
698
+	}
699
+	nat.SortPortMap(ports, bindings)
700
+	for _, port := range ports {
701
+		expose := types.TransportPort{}
702
+		expose.Proto = types.ParseProtocol(port.Proto())
703
+		expose.Port = uint16(port.Int())
704
+		exposeList = append(exposeList, expose)
705
+
706
+		pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto}
707
+		binding := bindings[port]
708
+		for i := 0; i < len(binding); i++ {
709
+			pbCopy := pb.GetCopy()
710
+			pbCopy.HostPort = uint16(nat.Port(binding[i].HostPort).Int())
711
+			pbCopy.HostIP = net.ParseIP(binding[i].HostIp)
712
+			pbList = append(pbList, pbCopy)
713
+		}
714
+
715
+		if container.hostConfig.PublishAllPorts && len(binding) == 0 {
716
+			pbList = append(pbList, pb)
717
+		}
718
+	}
719
+
720
+	createOptions = append(createOptions,
721
+		libnetwork.CreateOptionPortMapping(pbList),
722
+		libnetwork.CreateOptionExposedPorts(exposeList))
723
+
724
+	if container.Config.MacAddress != "" {
725
+		mac, err := net.ParseMAC(container.Config.MacAddress)
726
+		if err != nil {
727
+			return nil, err
728
+		}
729
+
730
+		genericOption := options.Generic{
731
+			netlabel.MacAddress: mac,
732
+		}
733
+
734
+		createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption))
735
+	}
736
+
737
+	return createOptions, nil
738
+}
739
+
740
+func parseService(controller libnetwork.NetworkController, service string) (string, string, string) {
741
+	dn := controller.Config().Daemon.DefaultNetwork
742
+	dd := controller.Config().Daemon.DefaultDriver
743
+
744
+	snd := strings.Split(service, ".")
745
+	if len(snd) > 2 {
746
+		return strings.Join(snd[:len(snd)-2], "."), snd[len(snd)-2], snd[len(snd)-1]
747
+	}
748
+	if len(snd) > 1 {
749
+		return snd[0], snd[1], dd
750
+	}
751
+	return snd[0], dn, dd
752
+}
753
+
754
+func createNetwork(controller libnetwork.NetworkController, dnet string, driver string) (libnetwork.Network, error) {
755
+	createOptions := []libnetwork.NetworkOption{}
756
+	genericOption := options.Generic{}
757
+
758
+	// Bridge driver is special due to legacy reasons
759
+	if runconfig.NetworkMode(driver).IsBridge() {
760
+		genericOption[netlabel.GenericData] = map[string]interface{}{
761
+			"BridgeName":            dnet,
762
+			"AllowNonDefaultBridge": "true",
763
+		}
764
+		networkOption := libnetwork.NetworkOptionGeneric(genericOption)
765
+		createOptions = append(createOptions, networkOption)
766
+	}
767
+
768
+	return controller.NewNetwork(driver, dnet, createOptions...)
769
+}
770
+
771
+func (container *Container) secondaryNetworkRequired(primaryNetworkType string) bool {
772
+	switch primaryNetworkType {
773
+	case "bridge", "none", "host", "container":
774
+		return false
775
+	}
776
+
777
+	if container.daemon.config.DisableBridge {
778
+		return false
779
+	}
780
+
781
+	if container.Config.ExposedPorts != nil && len(container.Config.ExposedPorts) > 0 {
782
+		return true
783
+	}
784
+	if container.hostConfig.PortBindings != nil && len(container.hostConfig.PortBindings) > 0 {
785
+		return true
786
+	}
787
+	return false
788
+}
789
+
790
+func (container *Container) AllocateNetwork() error {
791
+	mode := container.hostConfig.NetworkMode
792
+	controller := container.daemon.netController
793
+	if container.Config.NetworkDisabled || mode.IsContainer() {
794
+		return nil
795
+	}
796
+
797
+	networkDriver := string(mode)
798
+	service := container.Config.PublishService
799
+	networkName := mode.NetworkName()
800
+	if mode.IsDefault() {
801
+		if service != "" {
802
+			service, networkName, networkDriver = parseService(controller, service)
803
+		} else {
804
+			networkName = controller.Config().Daemon.DefaultNetwork
805
+			networkDriver = controller.Config().Daemon.DefaultDriver
806
+		}
807
+	} else if service != "" {
808
+		return fmt.Errorf("conflicting options: publishing a service and network mode")
809
+	}
810
+
811
+	if runconfig.NetworkMode(networkDriver).IsBridge() && container.daemon.config.DisableBridge {
812
+		container.Config.NetworkDisabled = true
813
+		return nil
814
+	}
815
+
816
+	if service == "" {
817
+		// dot character "." has a special meaning to support SERVICE[.NETWORK] format.
818
+		// For backward compatiblity, replacing "." with "-", instead of failing
819
+		service = strings.Replace(container.Name, ".", "-", -1)
820
+		// Service names dont like "/" in them. removing it instead of failing for backward compatibility
821
+		service = strings.Replace(service, "/", "", -1)
822
+	}
823
+
824
+	if container.secondaryNetworkRequired(networkDriver) {
825
+		// Configure Bridge as secondary network for port binding purposes
826
+		if err := container.configureNetwork("bridge", service, "bridge", false); err != nil {
827
+			return err
828
+		}
829
+	}
830
+
831
+	if err := container.configureNetwork(networkName, service, networkDriver, mode.IsDefault()); err != nil {
832
+		return err
833
+	}
834
+
835
+	return container.WriteHostConfig()
836
+}
837
+
838
+func (container *Container) configureNetwork(networkName, service, networkDriver string, canCreateNetwork bool) error {
839
+	controller := container.daemon.netController
840
+	n, err := controller.NetworkByName(networkName)
841
+	if err != nil {
842
+		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok || !canCreateNetwork {
843
+			return err
844
+		}
845
+
846
+		if n, err = createNetwork(controller, networkName, networkDriver); err != nil {
847
+			return err
848
+		}
849
+	}
850
+
851
+	ep, err := n.EndpointByName(service)
852
+	if err != nil {
853
+		if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok {
854
+			return err
855
+		}
856
+
857
+		createOptions, err := container.buildCreateEndpointOptions()
858
+		if err != nil {
859
+			return err
860
+		}
861
+
862
+		ep, err = n.CreateEndpoint(service, createOptions...)
863
+		if err != nil {
864
+			return err
865
+		}
866
+	}
867
+
868
+	if err := container.updateNetworkSettings(n, ep); err != nil {
869
+		return err
870
+	}
871
+
872
+	joinOptions, err := container.buildJoinOptions()
873
+	if err != nil {
874
+		return err
875
+	}
876
+
877
+	if err := ep.Join(container.ID, joinOptions...); err != nil {
878
+		return err
879
+	}
880
+
881
+	if err := container.updateJoinInfo(ep); err != nil {
882
+		return fmt.Errorf("Updating join info failed: %v", err)
883
+	}
884
+
885
+	return nil
886
+}
887
+
888
+func (container *Container) initializeNetworking() error {
889
+	var err error
890
+
891
+	// Make sure NetworkMode has an acceptable value before
892
+	// initializing networking.
893
+	if container.hostConfig.NetworkMode == runconfig.NetworkMode("") {
894
+		container.hostConfig.NetworkMode = runconfig.NetworkMode("default")
895
+	}
896
+	if container.hostConfig.NetworkMode.IsContainer() {
897
+		// we need to get the hosts files from the container to join
898
+		nc, err := container.getNetworkedContainer()
899
+		if err != nil {
900
+			return err
901
+		}
902
+		container.HostnamePath = nc.HostnamePath
903
+		container.HostsPath = nc.HostsPath
904
+		container.ResolvConfPath = nc.ResolvConfPath
905
+		container.Config.Hostname = nc.Config.Hostname
906
+		container.Config.Domainname = nc.Config.Domainname
907
+		return nil
908
+	}
909
+
910
+	if container.hostConfig.NetworkMode.IsHost() {
911
+		container.Config.Hostname, err = os.Hostname()
912
+		if err != nil {
913
+			return err
914
+		}
915
+
916
+		parts := strings.SplitN(container.Config.Hostname, ".", 2)
917
+		if len(parts) > 1 {
918
+			container.Config.Hostname = parts[0]
919
+			container.Config.Domainname = parts[1]
920
+		}
921
+
922
+	}
923
+
924
+	if err := container.AllocateNetwork(); err != nil {
925
+		return err
926
+	}
927
+
928
+	return container.buildHostnameFile()
929
+}
930
+
931
+func (container *Container) ExportRw() (archive.Archive, error) {
932
+	if container.daemon == nil {
933
+		return nil, fmt.Errorf("Can't load storage driver for unregistered container %s", container.ID)
934
+	}
935
+	archive, err := container.daemon.Diff(container)
936
+	if err != nil {
937
+		return nil, err
938
+	}
939
+	return ioutils.NewReadCloserWrapper(archive, func() error {
940
+			err := archive.Close()
941
+			return err
942
+		}),
943
+		nil
944
+}
945
+
946
+func (container *Container) getIpcContainer() (*Container, error) {
947
+	containerID := container.hostConfig.IpcMode.Container()
948
+	c, err := container.daemon.Get(containerID)
949
+	if err != nil {
950
+		return nil, err
951
+	}
952
+	if !c.IsRunning() {
953
+		return nil, fmt.Errorf("cannot join IPC of a non running container: %s", containerID)
954
+	}
955
+	return c, nil
956
+}
957
+
958
+func (container *Container) setupWorkingDirectory() error {
959
+	if container.Config.WorkingDir != "" {
960
+		container.Config.WorkingDir = filepath.Clean(container.Config.WorkingDir)
961
+
962
+		pth, err := container.GetResourcePath(container.Config.WorkingDir)
963
+		if err != nil {
964
+			return err
965
+		}
966
+
967
+		pthInfo, err := os.Stat(pth)
968
+		if err != nil {
969
+			if !os.IsNotExist(err) {
970
+				return err
971
+			}
972
+
973
+			if err := system.MkdirAll(pth, 0755); err != nil {
974
+				return err
975
+			}
976
+		}
977
+		if pthInfo != nil && !pthInfo.IsDir() {
978
+			return fmt.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)
979
+		}
980
+	}
981
+	return nil
982
+}
983
+
984
+func (container *Container) getNetworkedContainer() (*Container, error) {
985
+	parts := strings.SplitN(string(container.hostConfig.NetworkMode), ":", 2)
986
+	switch parts[0] {
987
+	case "container":
988
+		if len(parts) != 2 {
989
+			return nil, fmt.Errorf("no container specified to join network")
990
+		}
991
+		nc, err := container.daemon.Get(parts[1])
992
+		if err != nil {
993
+			return nil, err
994
+		}
995
+		if container == nc {
996
+			return nil, fmt.Errorf("cannot join own network")
997
+		}
998
+		if !nc.IsRunning() {
999
+			return nil, fmt.Errorf("cannot join network of a non running container: %s", parts[1])
1000
+		}
1001
+		return nc, nil
1002
+	default:
1003
+		return nil, fmt.Errorf("network mode not set to container")
1004
+	}
1005
+}
1006
+
1007
+func (container *Container) ReleaseNetwork() {
1008
+	if container.hostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
1009
+		return
1010
+	}
1011
+
1012
+	eid := container.NetworkSettings.EndpointID
1013
+	nid := container.NetworkSettings.NetworkID
1014
+
1015
+	container.NetworkSettings = &network.Settings{}
1016
+
1017
+	if nid == "" || eid == "" {
1018
+		return
1019
+	}
1020
+
1021
+	n, err := container.daemon.netController.NetworkByID(nid)
1022
+	if err != nil {
1023
+		logrus.Errorf("error locating network id %s: %v", nid, err)
1024
+		return
1025
+	}
1026
+
1027
+	ep, err := n.EndpointByID(eid)
1028
+	if err != nil {
1029
+		logrus.Errorf("error locating endpoint id %s: %v", eid, err)
1030
+		return
1031
+	}
1032
+
1033
+	switch {
1034
+	case container.hostConfig.NetworkMode.IsHost():
1035
+		if err := ep.Leave(container.ID); err != nil {
1036
+			logrus.Errorf("Error leaving endpoint id %s for container %s: %v", eid, container.ID, err)
1037
+			return
1038
+		}
1039
+	default:
1040
+		if err := container.daemon.netController.LeaveAll(container.ID); err != nil {
1041
+			logrus.Errorf("Leave all failed for  %s: %v", container.ID, err)
1042
+			return
1043
+		}
1044
+	}
1045
+
1046
+	// In addition to leaving all endpoints, delete implicitly created endpoint
1047
+	if container.Config.PublishService == "" {
1048
+		if err := ep.Delete(); err != nil {
1049
+			logrus.Errorf("deleting endpoint failed: %v", err)
1050
+		}
1051
+	}
1052
+
1053
+}
1054
+
1055
+func disableAllActiveLinks(container *Container) {
1056
+	if container.activeLinks != nil {
1057
+		for _, link := range container.activeLinks {
1058
+			link.Disable()
1059
+		}
1060
+	}
1061
+}
1062
+
1063
+func (container *Container) DisableLink(name string) {
1064
+	if container.activeLinks != nil {
1065
+		if link, exists := container.activeLinks[name]; exists {
1066
+			link.Disable()
1067
+			delete(container.activeLinks, name)
1068
+			if err := container.UpdateNetwork(); err != nil {
1069
+				logrus.Debugf("Could not update network to remove link: %v", err)
1070
+			}
1071
+		} else {
1072
+			logrus.Debugf("Could not find active link for %s", name)
1073
+		}
1074
+	}
1075
+}
1076
+
1077
+func (container *Container) UnmountVolumes(forceSyscall bool) error {
1078
+	var volumeMounts []mountPoint
1079
+
1080
+	for _, mntPoint := range container.MountPoints {
1081
+		dest, err := container.GetResourcePath(mntPoint.Destination)
1082
+		if err != nil {
1083
+			return err
1084
+		}
1085
+
1086
+		volumeMounts = append(volumeMounts, mountPoint{Destination: dest, Volume: mntPoint.Volume})
1087
+	}
1088
+
1089
+	for _, mnt := range container.networkMounts() {
1090
+		dest, err := container.GetResourcePath(mnt.Destination)
1091
+		if err != nil {
1092
+			return err
1093
+		}
1094
+
1095
+		volumeMounts = append(volumeMounts, mountPoint{Destination: dest})
1096
+	}
1097
+
1098
+	for _, volumeMount := range volumeMounts {
1099
+		if forceSyscall {
1100
+			syscall.Unmount(volumeMount.Destination, 0)
1101
+		}
1102
+
1103
+		if volumeMount.Volume != nil {
1104
+			if err := volumeMount.Volume.Unmount(); err != nil {
1105
+				return err
1106
+			}
1107
+		}
1108
+	}
1109
+
1110
+	return nil
1111
+}
1112
+
1113
+func (container *Container) PrepareStorage() error {
1114
+	return nil
1115
+}
1116
+
1117
+func (container *Container) CleanupStorage() error {
1118
+	return nil
1119
+}
... ...
@@ -4,10 +4,14 @@ package daemon
4 4
 
5 5
 import (
6 6
 	"fmt"
7
+	"path/filepath"
7 8
 	"strings"
8 9
 
9 10
 	"github.com/docker/docker/daemon/execdriver"
11
+	"github.com/docker/docker/daemon/graphdriver/windows"
12
+	"github.com/docker/docker/graph"
10 13
 	"github.com/docker/docker/pkg/archive"
14
+	"github.com/microsoft/hcsshim"
11 15
 )
12 16
 
13 17
 // This is deliberately empty on Windows as the default path will be set by
... ...
@@ -102,6 +106,26 @@ func populateCommand(c *Container, env []string) error {
102 102
 
103 103
 	processConfig.Env = env
104 104
 
105
+	var layerFolder string
106
+	var layerPaths []string
107
+
108
+	// The following is specific to the Windows driver. We do this to
109
+	// enable VFS to continue operating for development purposes.
110
+	if wd, ok := c.daemon.driver.(*windows.WindowsGraphDriver); ok {
111
+		var err error
112
+		var img *graph.Image
113
+		var ids []string
114
+
115
+		if img, err = c.daemon.graph.Get(c.ImageID); err != nil {
116
+			return fmt.Errorf("Failed to graph.Get on ImageID %s - %s", c.ImageID, err)
117
+		}
118
+		if ids, err = c.daemon.graph.ParentLayerIds(img); err != nil {
119
+			return fmt.Errorf("Failed to get parentlayer ids %s", img.ID)
120
+		}
121
+		layerPaths = wd.LayerIdsToPaths(ids)
122
+		layerFolder = filepath.Join(wd.Info().HomeDir, filepath.Base(c.ID))
123
+	}
124
+
105 125
 	// TODO Windows: Factor out remainder of unused fields.
106 126
 	c.command = &execdriver.Command{
107 127
 		ID:             c.ID,
... ...
@@ -118,6 +142,8 @@ func populateCommand(c *Container, env []string) error {
118 118
 		ProcessLabel:   c.GetProcessLabel(),
119 119
 		MountLabel:     c.GetMountLabel(),
120 120
 		FirstStart:     !c.HasBeenStartedBefore,
121
+		LayerFolder:    layerFolder,
122
+		LayerPaths:     layerPaths,
121 123
 	}
122 124
 
123 125
 	return nil
... ...
@@ -165,3 +191,33 @@ func (container *Container) DisableLink(name string) {
165 165
 func (container *Container) UnmountVolumes(forceSyscall bool) error {
166 166
 	return nil
167 167
 }
168
+
169
+func (container *Container) PrepareStorage() error {
170
+	if wd, ok := container.daemon.driver.(*windows.WindowsGraphDriver); ok {
171
+		// Get list of paths to parent layers.
172
+		var ids []string
173
+		if container.ImageID != "" {
174
+			img, err := container.daemon.graph.Get(container.ImageID)
175
+			if err != nil {
176
+				return err
177
+			}
178
+
179
+			ids, err = container.daemon.graph.ParentLayerIds(img)
180
+			if err != nil {
181
+				return err
182
+			}
183
+		}
184
+
185
+		if err := hcsshim.PrepareLayer(wd.Info(), container.ID, wd.LayerIdsToPaths(ids)); err != nil {
186
+			return err
187
+		}
188
+	}
189
+	return nil
190
+}
191
+
192
+func (container *Container) CleanupStorage() error {
193
+	if wd, ok := container.daemon.driver.(*windows.WindowsGraphDriver); ok {
194
+		return hcsshim.UnprepareLayer(wd.Info(), container.ID)
195
+	}
196
+	return nil
197
+}
... ...
@@ -8,7 +8,6 @@ import (
8 8
 
9 9
 	"github.com/Sirupsen/logrus"
10 10
 	"github.com/docker/docker/graph"
11
-	"github.com/docker/docker/image"
12 11
 	"github.com/docker/docker/pkg/parsers"
13 12
 	"github.com/docker/docker/pkg/stringid"
14 13
 	"github.com/docker/docker/runconfig"
... ...
@@ -47,7 +46,7 @@ func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.Hos
47 47
 	var (
48 48
 		container *Container
49 49
 		warnings  []string
50
-		img       *image.Image
50
+		img       *graph.Image
51 51
 		imgID     string
52 52
 		err       error
53 53
 	)
... ...
@@ -23,7 +23,6 @@ import (
23 23
 	"github.com/docker/docker/daemon/logger"
24 24
 	"github.com/docker/docker/daemon/network"
25 25
 	"github.com/docker/docker/graph"
26
-	"github.com/docker/docker/image"
27 26
 	"github.com/docker/docker/pkg/broadcastwriter"
28 27
 	"github.com/docker/docker/pkg/fileutils"
29 28
 	"github.com/docker/docker/pkg/graphdb"
... ...
@@ -338,7 +337,7 @@ func (daemon *Daemon) restore() error {
338 338
 	return nil
339 339
 }
340 340
 
341
-func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *image.Image) error {
341
+func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *graph.Image) error {
342 342
 	if img != nil && img.Config != nil {
343 343
 		if err := runconfig.Merge(config, img.Config); err != nil {
344 344
 			return err
... ...
@@ -879,7 +878,7 @@ func (daemon *Daemon) ContainerGraph() *graphdb.Database {
879 879
 	return daemon.containerGraph
880 880
 }
881 881
 
882
-func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*image.Image, error) {
882
+func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*graph.Image, error) {
883 883
 	// Retrieve all images
884 884
 	images, err := daemon.Graph().Map()
885 885
 	if err != nil {
... ...
@@ -896,7 +895,7 @@ func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*i
896 896
 	}
897 897
 
898 898
 	// Loop on the children of the given image and check the config
899
-	var match *image.Image
899
+	var match *graph.Image
900 900
 	for elem := range imageMap[imgID] {
901 901
 		img, ok := images[elem]
902 902
 		if !ok {
... ...
@@ -6,11 +6,14 @@ import (
6 6
 	"runtime"
7 7
 	"syscall"
8 8
 
9
+	"github.com/Sirupsen/logrus"
9 10
 	"github.com/docker/docker/daemon/graphdriver"
11
+	"github.com/docker/docker/daemon/graphdriver/windows"
10 12
 	"github.com/docker/docker/pkg/archive"
11 13
 	"github.com/docker/docker/pkg/parsers"
12 14
 	"github.com/docker/docker/runconfig"
13 15
 	"github.com/docker/libnetwork"
16
+	"github.com/microsoft/hcsshim"
14 17
 )
15 18
 
16 19
 func (daemon *Daemon) Changes(container *Container) ([]archive.Change, error) {
... ...
@@ -31,8 +34,36 @@ func (daemon *Daemon) createRootfs(container *Container) error {
31 31
 	if err := os.Mkdir(container.root, 0700); err != nil {
32 32
 		return err
33 33
 	}
34
-	if err := daemon.driver.Create(container.ID, container.ImageID); err != nil {
35
-		return err
34
+
35
+	if wd, ok := daemon.driver.(*windows.WindowsGraphDriver); ok {
36
+		if container.ImageID != "" {
37
+			// Get list of paths to parent layers.
38
+			logrus.Debugln("createRootfs: Container has parent image:", container.ImageID)
39
+			img, err := daemon.graph.Get(container.ImageID)
40
+			if err != nil {
41
+				return err
42
+			}
43
+
44
+			ids, err := daemon.graph.ParentLayerIds(img)
45
+			if err != nil {
46
+				return err
47
+			}
48
+			logrus.Debugf("Got image ids: %d", len(ids))
49
+
50
+			if err := hcsshim.CreateSandboxLayer(wd.Info(), container.ID, container.ImageID, wd.LayerIdsToPaths(ids)); err != nil {
51
+				return err
52
+			}
53
+		} else {
54
+			if err := daemon.driver.Create(container.ID, container.ImageID); err != nil {
55
+				return err
56
+			}
57
+		}
58
+	} else {
59
+		// Fall-back code path to allow the use of the VFS driver for development
60
+		if err := daemon.driver.Create(container.ID, container.ImageID); err != nil {
61
+			return err
62
+		}
63
+
36 64
 	}
37 65
 	return nil
38 66
 }
... ...
@@ -101,6 +101,7 @@ func GetDriver(name, home string, options []string) (Driver, error) {
101 101
 	if initFunc, exists := drivers[name]; exists {
102 102
 		return initFunc(filepath.Join(home, name), options)
103 103
 	}
104
+	logrus.Errorf("Failed to GetDriver graph %s %s", name, home)
104 105
 	return nil, ErrNotSupported
105 106
 }
106 107
 
... ...
@@ -1,14 +1,24 @@
1 1
 package graphdriver
2 2
 
3
-type DiffDiskDriver interface {
3
+import (
4
+	"github.com/docker/docker/pkg/archive"
5
+	"github.com/microsoft/hcsshim"
6
+)
7
+
8
+type WindowsGraphDriver interface {
4 9
 	Driver
5
-	CopyDiff(id, sourceId string) error
10
+	CopyDiff(id, sourceId string, parentLayerPaths []string) error
11
+	LayerIdsToPaths(ids []string) []string
12
+	Info() hcsshim.DriverInfo
13
+	Export(id string, parentLayerPaths []string) (archive.Archive, error)
14
+	Import(id string, layerData archive.ArchiveReader, parentLayerPaths []string) (int64, error)
6 15
 }
7 16
 
8 17
 var (
9 18
 	// Slice of drivers that should be used in order
10 19
 	priority = []string{
11
-		"windows",
20
+		"windowsfilter",
21
+		"windowsdiff",
12 22
 		"vfs",
13 23
 	}
14 24
 )
15 25
new file mode 100644
... ...
@@ -0,0 +1,326 @@
0
+//+build windows
1
+
2
+package windows
3
+
4
+import (
5
+	"fmt"
6
+	"os"
7
+	"path/filepath"
8
+	"sync"
9
+	"time"
10
+
11
+	"github.com/Sirupsen/logrus"
12
+	"github.com/docker/docker/daemon/graphdriver"
13
+	"github.com/docker/docker/pkg/archive"
14
+	"github.com/docker/docker/pkg/chrootarchive"
15
+	"github.com/docker/docker/pkg/ioutils"
16
+	"github.com/microsoft/hcsshim"
17
+)
18
+
19
+func init() {
20
+	graphdriver.Register("windowsfilter", InitFilter)
21
+	graphdriver.Register("windowsdiff", InitDiff)
22
+}
23
+
24
+const (
25
+	diffDriver = iota
26
+	filterDriver
27
+)
28
+
29
+type WindowsGraphDriver struct {
30
+	info       hcsshim.DriverInfo
31
+	sync.Mutex // Protects concurrent modification to active
32
+	active     map[string]int
33
+}
34
+
35
+// New returns a new Windows storage filter driver.
36
+func InitFilter(home string, options []string) (graphdriver.Driver, error) {
37
+	logrus.Debugf("WindowsGraphDriver InitFilter at %s", home)
38
+	d := &WindowsGraphDriver{
39
+		info: hcsshim.DriverInfo{
40
+			HomeDir: home,
41
+			Flavour: filterDriver,
42
+		},
43
+		active: make(map[string]int),
44
+	}
45
+	return d, nil
46
+}
47
+
48
+// New returns a new Windows differencing disk driver.
49
+func InitDiff(home string, options []string) (graphdriver.Driver, error) {
50
+	logrus.Debugf("WindowsGraphDriver InitDiff at %s", home)
51
+	d := &WindowsGraphDriver{
52
+		info: hcsshim.DriverInfo{
53
+			HomeDir: home,
54
+			Flavour: diffDriver,
55
+		},
56
+		active: make(map[string]int),
57
+	}
58
+	return d, nil
59
+}
60
+
61
+func (d *WindowsGraphDriver) Info() hcsshim.DriverInfo {
62
+	return d.info
63
+}
64
+
65
+func (d *WindowsGraphDriver) String() string {
66
+	switch d.info.Flavour {
67
+	case diffDriver:
68
+		return "windowsdiff"
69
+	case filterDriver:
70
+		return "windowsfilter"
71
+	default:
72
+		return "Unknown driver flavour"
73
+	}
74
+}
75
+
76
+func (d *WindowsGraphDriver) Status() [][2]string {
77
+	return [][2]string{
78
+		{"Windows", ""},
79
+	}
80
+}
81
+
82
+// Exists returns true if the given id is registered with
83
+// this driver
84
+func (d *WindowsGraphDriver) Exists(id string) bool {
85
+	result, err := hcsshim.LayerExists(d.info, id)
86
+	if err != nil {
87
+		return false
88
+	}
89
+	return result
90
+}
91
+
92
+func (d *WindowsGraphDriver) Create(id, parent string) error {
93
+	return hcsshim.CreateLayer(d.info, id, parent)
94
+}
95
+
96
+func (d *WindowsGraphDriver) dir(id string) string {
97
+	return filepath.Join(d.info.HomeDir, filepath.Base(id))
98
+}
99
+
100
+// Remove unmounts and removes the dir information
101
+func (d *WindowsGraphDriver) Remove(id string) error {
102
+	return hcsshim.DestroyLayer(d.info, id)
103
+}
104
+
105
+// Get returns the rootfs path for the id. This will mount the dir at it's given path
106
+func (d *WindowsGraphDriver) Get(id, mountLabel string) (string, error) {
107
+	var dir string
108
+
109
+	d.Lock()
110
+	defer d.Unlock()
111
+
112
+	if d.active[id] == 0 {
113
+		if err := hcsshim.ActivateLayer(d.info, id); err != nil {
114
+			return "", err
115
+		}
116
+	}
117
+
118
+	mountPath, err := hcsshim.GetLayerMountPath(d.info, id)
119
+	if err != nil {
120
+		return "", err
121
+	}
122
+
123
+	// If the layer has a mount path, use that. Otherwise, use the
124
+	// folder path.
125
+	if mountPath != "" {
126
+		dir = mountPath
127
+	} else {
128
+		dir = d.dir(id)
129
+	}
130
+
131
+	d.active[id]++
132
+
133
+	return dir, nil
134
+}
135
+
136
+func (d *WindowsGraphDriver) Put(id string) error {
137
+	logrus.Debugf("WindowsGraphDriver Put() id %s", id)
138
+
139
+	d.Lock()
140
+	defer d.Unlock()
141
+
142
+	if d.active[id] > 1 {
143
+		d.active[id]--
144
+	} else if d.active[id] == 1 {
145
+		if err := hcsshim.DeactivateLayer(d.info, id); err != nil {
146
+			return err
147
+		}
148
+		delete(d.active, id)
149
+	}
150
+
151
+	return nil
152
+}
153
+
154
+func (d *WindowsGraphDriver) Cleanup() error {
155
+	return nil
156
+}
157
+
158
+// Diff produces an archive of the changes between the specified
159
+// layer and its parent layer which may be "".
160
+func (d *WindowsGraphDriver) Diff(id, parent string) (arch archive.Archive, err error) {
161
+	return nil, fmt.Errorf("The Windows graphdriver does not support Diff()")
162
+}
163
+
164
+// Changes produces a list of changes between the specified layer
165
+// and its parent layer. If parent is "", then all changes will be ADD changes.
166
+func (d *WindowsGraphDriver) Changes(id, parent string) ([]archive.Change, error) {
167
+	return nil, fmt.Errorf("The Windows graphdriver does not support Changes()")
168
+}
169
+
170
+// ApplyDiff extracts the changeset from the given diff into the
171
+// layer with the specified id and parent, returning the size of the
172
+// new layer in bytes.
173
+func (d *WindowsGraphDriver) ApplyDiff(id, parent string, diff archive.ArchiveReader) (size int64, err error) {
174
+	start := time.Now().UTC()
175
+	logrus.Debugf("WindowsGraphDriver ApplyDiff: Start untar layer")
176
+
177
+	destination := d.dir(id)
178
+	if d.info.Flavour == diffDriver {
179
+		destination = filepath.Dir(destination)
180
+	}
181
+
182
+	if size, err = chrootarchive.ApplyLayer(destination, diff); err != nil {
183
+		return
184
+	}
185
+	logrus.Debugf("WindowsGraphDriver ApplyDiff: Untar time: %vs", time.Now().UTC().Sub(start).Seconds())
186
+
187
+	return
188
+}
189
+
190
+// DiffSize calculates the changes between the specified layer
191
+// and its parent and returns the size in bytes of the changes
192
+// relative to its base filesystem directory.
193
+func (d *WindowsGraphDriver) DiffSize(id, parent string) (size int64, err error) {
194
+	changes, err := d.Changes(id, parent)
195
+	if err != nil {
196
+		return
197
+	}
198
+
199
+	layerFs, err := d.Get(id, "")
200
+	if err != nil {
201
+		return
202
+	}
203
+	defer d.Put(id)
204
+
205
+	return archive.ChangesSize(layerFs, changes), nil
206
+}
207
+
208
+func (d *WindowsGraphDriver) CopyDiff(sourceId, id string, parentLayerPaths []string) error {
209
+	d.Lock()
210
+	defer d.Unlock()
211
+
212
+	if d.info.Flavour == filterDriver && d.active[sourceId] == 0 {
213
+		if err := hcsshim.ActivateLayer(d.info, sourceId); err != nil {
214
+			return err
215
+		}
216
+		defer func() {
217
+			err := hcsshim.DeactivateLayer(d.info, sourceId)
218
+			if err != nil {
219
+				logrus.Warnf("Failed to Deactivate %s: %s", sourceId, err)
220
+			}
221
+		}()
222
+	}
223
+
224
+	return hcsshim.CopyLayer(d.info, sourceId, id, parentLayerPaths)
225
+}
226
+
227
+func (d *WindowsGraphDriver) LayerIdsToPaths(ids []string) []string {
228
+	var paths []string
229
+	for _, id := range ids {
230
+		path, err := d.Get(id, "")
231
+		if err != nil {
232
+			logrus.Debug("LayerIdsToPaths: Error getting mount path for id", id, ":", err.Error())
233
+			return nil
234
+		}
235
+		if d.Put(id) != nil {
236
+			logrus.Debug("LayerIdsToPaths: Error putting mount path for id", id, ":", err.Error())
237
+			return nil
238
+		}
239
+		paths = append(paths, path)
240
+	}
241
+	return paths
242
+}
243
+
244
+func (d *WindowsGraphDriver) GetMetadata(id string) (map[string]string, error) {
245
+	return nil, nil
246
+}
247
+
248
+func (d *WindowsGraphDriver) Export(id string, parentLayerPaths []string) (arch archive.Archive, err error) {
249
+	layerFs, err := d.Get(id, "")
250
+	if err != nil {
251
+		return
252
+	}
253
+	defer func() {
254
+		if err != nil {
255
+			d.Put(id)
256
+		}
257
+	}()
258
+
259
+	tempFolder := layerFs + "-temp"
260
+	if err = os.MkdirAll(tempFolder, 0755); err != nil {
261
+		logrus.Errorf("Could not create %s %s", tempFolder, err)
262
+		return
263
+	}
264
+	defer func() {
265
+		if err != nil {
266
+			if err2 := os.RemoveAll(tempFolder); err2 != nil {
267
+				logrus.Warnf("Couldn't clean-up tempFolder: %s %s", tempFolder, err2)
268
+			}
269
+		}
270
+	}()
271
+
272
+	if err = hcsshim.ExportLayer(d.info, id, tempFolder, parentLayerPaths); err != nil {
273
+		return
274
+	}
275
+
276
+	archive, err := archive.Tar(tempFolder, archive.Uncompressed)
277
+	if err != nil {
278
+		return
279
+	}
280
+	return ioutils.NewReadCloserWrapper(archive, func() error {
281
+		err := archive.Close()
282
+		d.Put(id)
283
+		if err2 := os.RemoveAll(tempFolder); err2 != nil {
284
+			logrus.Warnf("Couldn't clean-up tempFolder: %s %s", tempFolder, err2)
285
+		}
286
+		return err
287
+	}), nil
288
+
289
+}
290
+
291
+func (d *WindowsGraphDriver) Import(id string, layerData archive.ArchiveReader, parentLayerPaths []string) (size int64, err error) {
292
+	layerFs, err := d.Get(id, "")
293
+	if err != nil {
294
+		return
295
+	}
296
+	defer func() {
297
+		if err != nil {
298
+			d.Put(id)
299
+		}
300
+	}()
301
+
302
+	tempFolder := layerFs + "-temp"
303
+	if err = os.MkdirAll(tempFolder, 0755); err != nil {
304
+		logrus.Errorf("Could not create %s %s", tempFolder, err)
305
+		return
306
+	}
307
+	defer func() {
308
+		if err2 := os.RemoveAll(tempFolder); err2 != nil {
309
+			logrus.Warnf("Couldn't clean-up tempFolder: %s %s", tempFolder, err2)
310
+		}
311
+	}()
312
+
313
+	start := time.Now().UTC()
314
+	logrus.Debugf("Start untar layer")
315
+	if size, err = chrootarchive.ApplyLayer(tempFolder, layerData); err != nil {
316
+		return
317
+	}
318
+	logrus.Debugf("Untar time: %vs", time.Now().UTC().Sub(start).Seconds())
319
+
320
+	if err = hcsshim.ImportLayer(d.info, id, tempFolder, parentLayerPaths); err != nil {
321
+		return
322
+	}
323
+
324
+	return
325
+}
... ...
@@ -7,7 +7,6 @@ import (
7 7
 	"github.com/Sirupsen/logrus"
8 8
 	"github.com/docker/docker/api/types"
9 9
 	"github.com/docker/docker/graph"
10
-	"github.com/docker/docker/image"
11 10
 	"github.com/docker/docker/pkg/parsers"
12 11
 	"github.com/docker/docker/pkg/stringid"
13 12
 	"github.com/docker/docker/utils"
... ...
@@ -160,7 +159,7 @@ func (daemon *Daemon) canDeleteImage(imgID string, force bool) error {
160 160
 			return err
161 161
 		}
162 162
 
163
-		if err := daemon.graph.WalkHistory(parent, func(p image.Image) error {
163
+		if err := daemon.graph.WalkHistory(parent, func(p graph.Image) error {
164 164
 			if imgID == p.ID {
165 165
 				if container.IsRunning() {
166 166
 					if force {
... ...
@@ -9,6 +9,7 @@ import (
9 9
 
10 10
 	"github.com/Sirupsen/logrus"
11 11
 	"github.com/docker/docker/pkg/chrootarchive"
12
+	"github.com/docker/docker/pkg/system"
12 13
 	"github.com/docker/docker/runconfig"
13 14
 	"github.com/docker/docker/volume"
14 15
 	"github.com/docker/docker/volume/local"
... ...
@@ -35,7 +36,7 @@ func (m *mountPoint) Setup() (string, error) {
35 35
 			if !os.IsNotExist(err) {
36 36
 				return "", err
37 37
 			}
38
-			if err := os.MkdirAll(m.Source, 0755); err != nil {
38
+			if err := system.MkdirAll(m.Source, 0755); err != nil {
39 39
 				return "", err
40 40
 			}
41 41
 		}
... ...
@@ -18,6 +18,7 @@ import (
18 18
 	flag "github.com/docker/docker/pkg/mflag"
19 19
 	"github.com/docker/docker/pkg/pidfile"
20 20
 	"github.com/docker/docker/pkg/signal"
21
+	"github.com/docker/docker/pkg/system"
21 22
 	"github.com/docker/docker/pkg/timeutils"
22 23
 	"github.com/docker/docker/pkg/tlsconfig"
23 24
 	"github.com/docker/docker/registry"
... ...
@@ -51,7 +52,7 @@ func migrateKey() (err error) {
51 51
 			}
52 52
 		}()
53 53
 
54
-		if err := os.MkdirAll(getDaemonConfDir(), os.FileMode(0644)); err != nil {
54
+		if err := system.MkdirAll(getDaemonConfDir(), os.FileMode(0644)); err != nil {
55 55
 			return fmt.Errorf("Unable to create daemon configuration directory: %s", err)
56 56
 		}
57 57
 
... ...
@@ -37,6 +37,22 @@ type Graph struct {
37 37
 	imageMutex imageMutex // protect images in driver.
38 38
 }
39 39
 
40
+type Image struct {
41
+	ID              string            `json:"id"`
42
+	Parent          string            `json:"parent,omitempty"`
43
+	Comment         string            `json:"comment,omitempty"`
44
+	Created         time.Time         `json:"created"`
45
+	Container       string            `json:"container,omitempty"`
46
+	ContainerConfig runconfig.Config  `json:"container_config,omitempty"`
47
+	DockerVersion   string            `json:"docker_version,omitempty"`
48
+	Author          string            `json:"author,omitempty"`
49
+	Config          *runconfig.Config `json:"config,omitempty"`
50
+	Architecture    string            `json:"architecture,omitempty"`
51
+	OS              string            `json:"os,omitempty"`
52
+	Size            int64
53
+	graph           Graph
54
+}
55
+
40 56
 var (
41 57
 	// ErrDigestNotSet is used when request the digest for a layer
42 58
 	// but the layer has no digest value or content to compute the
... ...
@@ -79,6 +95,13 @@ func (graph *Graph) restore() error {
79 79
 			ids = append(ids, id)
80 80
 		}
81 81
 	}
82
+
83
+	baseIds, err := graph.restoreBaseImages()
84
+	if err != nil {
85
+		return err
86
+	}
87
+	ids = append(ids, baseIds...)
88
+
82 89
 	graph.idIndex = truncindex.NewTruncIndex(ids)
83 90
 	logrus.Debugf("Restored %d elements", len(ids))
84 91
 	return nil
... ...
@@ -100,7 +123,7 @@ func (graph *Graph) Exists(id string) bool {
100 100
 }
101 101
 
102 102
 // Get returns the image with the given id, or an error if the image doesn't exist.
103
-func (graph *Graph) Get(name string) (*image.Image, error) {
103
+func (graph *Graph) Get(name string) (*Image, error) {
104 104
 	id, err := graph.idIndex.Get(name)
105 105
 	if err != nil {
106 106
 		return nil, fmt.Errorf("could not find image: %v", err)
... ...
@@ -128,8 +151,8 @@ func (graph *Graph) Get(name string) (*image.Image, error) {
128 128
 }
129 129
 
130 130
 // Create creates a new image and registers it in the graph.
131
-func (graph *Graph) Create(layerData archive.ArchiveReader, containerID, containerImage, comment, author string, containerConfig, config *runconfig.Config) (*image.Image, error) {
132
-	img := &image.Image{
131
+func (graph *Graph) Create(layerData archive.ArchiveReader, containerID, containerImage, comment, author string, containerConfig, config *runconfig.Config) (*Image, error) {
132
+	img := &Image{
133 133
 		ID:            stringid.GenerateRandomID(),
134 134
 		Comment:       comment,
135 135
 		Created:       time.Now().UTC(),
... ...
@@ -153,7 +176,7 @@ func (graph *Graph) Create(layerData archive.ArchiveReader, containerID, contain
153 153
 }
154 154
 
155 155
 // Register imports a pre-existing image into the graph.
156
-func (graph *Graph) Register(img *image.Image, layerData archive.ArchiveReader) (err error) {
156
+func (graph *Graph) Register(img *Image, layerData archive.ArchiveReader) (err error) {
157 157
 	if err := image.ValidateID(img.ID); err != nil {
158 158
 		return err
159 159
 	}
... ...
@@ -197,9 +220,10 @@ func (graph *Graph) Register(img *image.Image, layerData archive.ArchiveReader)
197 197
 	}
198 198
 
199 199
 	// Create root filesystem in the driver
200
-	if err := graph.driver.Create(img.ID, img.Parent); err != nil {
201
-		return fmt.Errorf("Driver %s failed to create image rootfs %s: %s", graph.driver, img.ID, err)
200
+	if err := createRootFilesystemInDriver(graph, img, layerData); err != nil {
201
+		return err
202 202
 	}
203
+
203 204
 	// Apply the diff/layer
204 205
 	if err := graph.storeImage(img, layerData, tmp); err != nil {
205 206
 		return err
... ...
@@ -303,9 +327,9 @@ func (graph *Graph) Delete(name string) error {
303 303
 }
304 304
 
305 305
 // Map returns a list of all images in the graph, addressable by ID.
306
-func (graph *Graph) Map() (map[string]*image.Image, error) {
307
-	images := make(map[string]*image.Image)
308
-	err := graph.walkAll(func(image *image.Image) {
306
+func (graph *Graph) Map() (map[string]*Image, error) {
307
+	images := make(map[string]*Image)
308
+	err := graph.walkAll(func(image *Image) {
309 309
 		images[image.ID] = image
310 310
 	})
311 311
 	if err != nil {
... ...
@@ -316,7 +340,7 @@ func (graph *Graph) Map() (map[string]*image.Image, error) {
316 316
 
317 317
 // walkAll iterates over each image in the graph, and passes it to a handler.
318 318
 // The walking order is undetermined.
319
-func (graph *Graph) walkAll(handler func(*image.Image)) error {
319
+func (graph *Graph) walkAll(handler func(*Image)) error {
320 320
 	files, err := ioutil.ReadDir(graph.root)
321 321
 	if err != nil {
322 322
 		return err
... ...
@@ -336,9 +360,9 @@ func (graph *Graph) walkAll(handler func(*image.Image)) error {
336 336
 // If an image of id ID has 3 children images, then the value for key ID
337 337
 // will be a list of 3 images.
338 338
 // If an image has no children, it will not have an entry in the table.
339
-func (graph *Graph) ByParent() (map[string][]*image.Image, error) {
340
-	byParent := make(map[string][]*image.Image)
341
-	err := graph.walkAll(func(img *image.Image) {
339
+func (graph *Graph) ByParent() (map[string][]*Image, error) {
340
+	byParent := make(map[string][]*Image)
341
+	err := graph.walkAll(func(img *Image) {
342 342
 		parent, err := graph.Get(img.Parent)
343 343
 		if err != nil {
344 344
 			return
... ...
@@ -346,7 +370,7 @@ func (graph *Graph) ByParent() (map[string][]*image.Image, error) {
346 346
 		if children, exists := byParent[parent.ID]; exists {
347 347
 			byParent[parent.ID] = append(children, img)
348 348
 		} else {
349
-			byParent[parent.ID] = []*image.Image{img}
349
+			byParent[parent.ID] = []*Image{img}
350 350
 		}
351 351
 	})
352 352
 	return byParent, err
... ...
@@ -354,13 +378,13 @@ func (graph *Graph) ByParent() (map[string][]*image.Image, error) {
354 354
 
355 355
 // Heads returns all heads in the graph, keyed by id.
356 356
 // A head is an image which is not the parent of another image in the graph.
357
-func (graph *Graph) Heads() (map[string]*image.Image, error) {
358
-	heads := make(map[string]*image.Image)
357
+func (graph *Graph) Heads() (map[string]*Image, error) {
358
+	heads := make(map[string]*Image)
359 359
 	byParent, err := graph.ByParent()
360 360
 	if err != nil {
361 361
 		return nil, err
362 362
 	}
363
-	err = graph.walkAll(func(image *image.Image) {
363
+	err = graph.walkAll(func(image *Image) {
364 364
 		// If it's not in the byParent lookup table, then
365 365
 		// it's not a parent -> so it's a head!
366 366
 		if _, exists := byParent[image.ID]; !exists {
... ...
@@ -374,33 +398,8 @@ func (graph *Graph) imageRoot(id string) string {
374 374
 	return filepath.Join(graph.root, id)
375 375
 }
376 376
 
377
-// storeImage stores file system layer data for the given image to the
378
-// graph's storage driver. Image metadata is stored in a file
379
-// at the specified root directory.
380
-func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader, root string) (err error) {
381
-	// Store the layer. If layerData is not nil, unpack it into the new layer
382
-	if layerData != nil {
383
-		if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, layerData); err != nil {
384
-			return err
385
-		}
386
-	}
387
-
388
-	if err := graph.saveSize(root, int(img.Size)); err != nil {
389
-		return err
390
-	}
391
-
392
-	f, err := os.OpenFile(jsonPath(root), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
393
-	if err != nil {
394
-		return err
395
-	}
396
-
397
-	defer f.Close()
398
-
399
-	return json.NewEncoder(f).Encode(img)
400
-}
401
-
402 377
 // loadImage fetches the image with the given id from the graph.
403
-func (graph *Graph) loadImage(id string) (*image.Image, error) {
378
+func (graph *Graph) loadImage(id string) (*Image, error) {
404 379
 	root := graph.imageRoot(id)
405 380
 
406 381
 	// Open the JSON file to decode by streaming
... ...
@@ -410,7 +409,7 @@ func (graph *Graph) loadImage(id string) (*image.Image, error) {
410 410
 	}
411 411
 	defer jsonSource.Close()
412 412
 
413
-	img := &image.Image{}
413
+	img := &Image{}
414 414
 	dec := json.NewDecoder(jsonSource)
415 415
 
416 416
 	// Decode the JSON data
... ...
@@ -488,7 +487,13 @@ func jsonPath(root string) string {
488 488
 	return filepath.Join(root, "json")
489 489
 }
490 490
 
491
-// TarLayer returns a tar archive of the image's filesystem layer.
492
-func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) {
493
-	return graph.driver.Diff(img.ID, img.Parent)
491
+// Build an Image object from raw json data
492
+func NewImgJSON(src []byte) (*Image, error) {
493
+	ret := &Image{}
494
+
495
+	// FIXME: Is there a cleaner way to "purify" the input json?
496
+	if err := json.Unmarshal(src, ret); err != nil {
497
+		return nil, err
498
+	}
499
+	return ret, nil
494 500
 }
... ...
@@ -68,7 +68,7 @@ func TestInterruptedRegister(t *testing.T) {
68 68
 	graph, _ := tempGraph(t)
69 69
 	defer nukeGraph(graph)
70 70
 	badArchive, w := io.Pipe() // Use a pipe reader as a fake archive which never yields data
71
-	image := &image.Image{
71
+	image := &Image{
72 72
 		ID:      stringid.GenerateRandomID(),
73 73
 		Comment: "testing",
74 74
 		Created: time.Now(),
... ...
@@ -128,7 +128,7 @@ func TestRegister(t *testing.T) {
128 128
 	if err != nil {
129 129
 		t.Fatal(err)
130 130
 	}
131
-	image := &image.Image{
131
+	image := &Image{
132 132
 		ID:      stringid.GenerateRandomID(),
133 133
 		Comment: "testing",
134 134
 		Created: time.Now(),
... ...
@@ -232,19 +232,19 @@ func TestByParent(t *testing.T) {
232 232
 
233 233
 	graph, _ := tempGraph(t)
234 234
 	defer nukeGraph(graph)
235
-	parentImage := &image.Image{
235
+	parentImage := &Image{
236 236
 		ID:      stringid.GenerateRandomID(),
237 237
 		Comment: "parent",
238 238
 		Created: time.Now(),
239 239
 		Parent:  "",
240 240
 	}
241
-	childImage1 := &image.Image{
241
+	childImage1 := &Image{
242 242
 		ID:      stringid.GenerateRandomID(),
243 243
 		Comment: "child1",
244 244
 		Created: time.Now(),
245 245
 		Parent:  parentImage.ID,
246 246
 	}
247
-	childImage2 := &image.Image{
247
+	childImage2 := &Image{
248 248
 		ID:      stringid.GenerateRandomID(),
249 249
 		Comment: "child2",
250 250
 		Created: time.Now(),
... ...
@@ -264,7 +264,7 @@ func TestByParent(t *testing.T) {
264 264
 	}
265 265
 }
266 266
 
267
-func createTestImage(graph *Graph, t *testing.T) *image.Image {
267
+func createTestImage(graph *Graph, t *testing.T) *Image {
268 268
 	archive, err := fakeTar()
269 269
 	if err != nil {
270 270
 		t.Fatal(err)
271 271
new file mode 100644
... ...
@@ -0,0 +1,114 @@
0
+// +build !windows
1
+
2
+package graph
3
+
4
+import (
5
+	"encoding/json"
6
+	"fmt"
7
+	"os"
8
+	"path/filepath"
9
+	"strings"
10
+	"syscall"
11
+
12
+	"github.com/docker/docker/pkg/archive"
13
+	"github.com/docker/docker/pkg/system"
14
+)
15
+
16
+// setupInitLayer populates a directory with mountpoints suitable
17
+// for bind-mounting dockerinit into the container. The mountpoint is simply an
18
+// empty file at /.dockerinit
19
+//
20
+// This extra layer is used by all containers as the top-most ro layer. It protects
21
+// the container from unwanted side-effects on the rw layer.
22
+func SetupInitLayer(initLayer string) error {
23
+	for pth, typ := range map[string]string{
24
+		"/dev/pts":         "dir",
25
+		"/dev/shm":         "dir",
26
+		"/proc":            "dir",
27
+		"/sys":             "dir",
28
+		"/.dockerinit":     "file",
29
+		"/.dockerenv":      "file",
30
+		"/etc/resolv.conf": "file",
31
+		"/etc/hosts":       "file",
32
+		"/etc/hostname":    "file",
33
+		"/dev/console":     "file",
34
+		"/etc/mtab":        "/proc/mounts",
35
+	} {
36
+		parts := strings.Split(pth, "/")
37
+		prev := "/"
38
+		for _, p := range parts[1:] {
39
+			prev = filepath.Join(prev, p)
40
+			syscall.Unlink(filepath.Join(initLayer, prev))
41
+		}
42
+
43
+		if _, err := os.Stat(filepath.Join(initLayer, pth)); err != nil {
44
+			if os.IsNotExist(err) {
45
+				if err := system.MkdirAll(filepath.Join(initLayer, filepath.Dir(pth)), 0755); err != nil {
46
+					return err
47
+				}
48
+				switch typ {
49
+				case "dir":
50
+					if err := system.MkdirAll(filepath.Join(initLayer, pth), 0755); err != nil {
51
+						return err
52
+					}
53
+				case "file":
54
+					f, err := os.OpenFile(filepath.Join(initLayer, pth), os.O_CREATE, 0755)
55
+					if err != nil {
56
+						return err
57
+					}
58
+					f.Close()
59
+				default:
60
+					if err := os.Symlink(typ, filepath.Join(initLayer, pth)); err != nil {
61
+						return err
62
+					}
63
+				}
64
+			} else {
65
+				return err
66
+			}
67
+		}
68
+	}
69
+
70
+	// Layer is ready to use, if it wasn't before.
71
+	return nil
72
+}
73
+
74
+func createRootFilesystemInDriver(graph *Graph, img *Image, layerData archive.ArchiveReader) error {
75
+	if err := graph.driver.Create(img.ID, img.Parent); err != nil {
76
+		return fmt.Errorf("Driver %s failed to create image rootfs %s: %s", graph.driver, img.ID, err)
77
+	}
78
+	return nil
79
+}
80
+
81
+func (graph *Graph) restoreBaseImages() ([]string, error) {
82
+	return nil, nil
83
+}
84
+
85
+// storeImage stores file system layer data for the given image to the
86
+// graph's storage driver. Image metadata is stored in a file
87
+// at the specified root directory.
88
+func (graph *Graph) storeImage(img *Image, layerData archive.ArchiveReader, root string) (err error) {
89
+	// Store the layer. If layerData is not nil, unpack it into the new layer
90
+	if layerData != nil {
91
+		if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, layerData); err != nil {
92
+			return err
93
+		}
94
+	}
95
+
96
+	if err := graph.saveSize(root, int(img.Size)); err != nil {
97
+		return err
98
+	}
99
+
100
+	f, err := os.OpenFile(jsonPath(root), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
101
+	if err != nil {
102
+		return err
103
+	}
104
+
105
+	defer f.Close()
106
+
107
+	return json.NewEncoder(f).Encode(img)
108
+}
109
+
110
+// TarLayer returns a tar archive of the image's filesystem layer.
111
+func (graph *Graph) TarLayer(img *Image) (arch archive.Archive, err error) {
112
+	return graph.driver.Diff(img.ID, img.Parent)
113
+}
0 114
new file mode 100644
... ...
@@ -0,0 +1,160 @@
0
+// +build windows
1
+
2
+package graph
3
+
4
+import (
5
+	"encoding/json"
6
+	"fmt"
7
+	"os"
8
+
9
+	"github.com/Sirupsen/logrus"
10
+	"github.com/docker/docker/daemon/graphdriver/windows"
11
+	"github.com/docker/docker/pkg/archive"
12
+)
13
+
14
+// setupInitLayer populates a directory with mountpoints suitable
15
+// for bind-mounting dockerinit into the container. T
16
+func SetupInitLayer(initLayer string) error {
17
+	return nil
18
+}
19
+
20
+func createRootFilesystemInDriver(graph *Graph, img *Image, layerData archive.ArchiveReader) error {
21
+	if wd, ok := graph.driver.(*windows.WindowsGraphDriver); ok {
22
+		if img.Container != "" && layerData == nil {
23
+			logrus.Debugf("Copying from container %s.", img.Container)
24
+
25
+			var ids []string
26
+			if img.Parent != "" {
27
+				parentImg, err := graph.Get(img.Parent)
28
+				if err != nil {
29
+					return err
30
+				}
31
+
32
+				ids, err = graph.ParentLayerIds(parentImg)
33
+				if err != nil {
34
+					return err
35
+				}
36
+			}
37
+
38
+			if err := wd.CopyDiff(img.Container, img.ID, wd.LayerIdsToPaths(ids)); err != nil {
39
+				return fmt.Errorf("Driver %s failed to copy image rootfs %s: %s", graph.driver, img.Container, err)
40
+			}
41
+		} else if img.Parent == "" {
42
+			if err := graph.driver.Create(img.ID, img.Parent); err != nil {
43
+				return fmt.Errorf("Driver %s failed to create image rootfs %s: %s", graph.driver, img.ID, err)
44
+			}
45
+		}
46
+	} else {
47
+		// This fallback allows the use of VFS during daemon development.
48
+		if err := graph.driver.Create(img.ID, img.Parent); err != nil {
49
+			return fmt.Errorf("Driver %s failed to create image rootfs %s: %s", graph.driver, img.ID, err)
50
+		}
51
+	}
52
+	return nil
53
+}
54
+
55
+func (graph *Graph) restoreBaseImages() ([]string, error) {
56
+	// TODO Windows. This needs implementing (@swernli)
57
+	return nil, nil
58
+}
59
+
60
+// ParentLayerIds returns a list of all parent image IDs for the given image.
61
+func (graph *Graph) ParentLayerIds(img *Image) (ids []string, err error) {
62
+	for i := img; i != nil && err == nil; i, err = graph.GetParent(i) {
63
+		ids = append(ids, i.ID)
64
+	}
65
+
66
+	return
67
+}
68
+
69
+// storeImage stores file system layer data for the given image to the
70
+// graph's storage driver. Image metadata is stored in a file
71
+// at the specified root directory.
72
+func (graph *Graph) storeImage(img *Image, layerData archive.ArchiveReader, root string) (err error) {
73
+
74
+	if wd, ok := graph.driver.(*windows.WindowsGraphDriver); ok {
75
+		// Store the layer. If layerData is not nil and this isn't a base image,
76
+		// unpack it into the new layer
77
+		if layerData != nil && img.Parent != "" {
78
+			var ids []string
79
+			if img.Parent != "" {
80
+				parentImg, err := graph.Get(img.Parent)
81
+				if err != nil {
82
+					return err
83
+				}
84
+
85
+				ids, err = graph.ParentLayerIds(parentImg)
86
+				if err != nil {
87
+					return err
88
+				}
89
+			}
90
+
91
+			if img.Size, err = wd.Import(img.ID, layerData, wd.LayerIdsToPaths(ids)); err != nil {
92
+				return err
93
+			}
94
+		}
95
+
96
+		if err := graph.saveSize(root, int(img.Size)); err != nil {
97
+			return err
98
+		}
99
+
100
+		f, err := os.OpenFile(jsonPath(root), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
101
+		if err != nil {
102
+			return err
103
+		}
104
+
105
+		defer f.Close()
106
+
107
+		return json.NewEncoder(f).Encode(img)
108
+	} else {
109
+		// We keep this functionality here so that we can still work with the
110
+		// VFS driver during development. This will not be used for actual running
111
+		// of Windows containers. Without this code, it would not be possible to
112
+		// docker pull using the VFS driver.
113
+
114
+		// Store the layer. If layerData is not nil, unpack it into the new layer
115
+		if layerData != nil {
116
+			if img.Size, err = graph.driver.ApplyDiff(img.ID, img.Parent, layerData); err != nil {
117
+				return err
118
+			}
119
+		}
120
+
121
+		if err := graph.saveSize(root, int(img.Size)); err != nil {
122
+			return err
123
+		}
124
+
125
+		f, err := os.OpenFile(jsonPath(root), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
126
+		if err != nil {
127
+			return err
128
+		}
129
+
130
+		defer f.Close()
131
+
132
+		return json.NewEncoder(f).Encode(img)
133
+	}
134
+}
135
+
136
+// TarLayer returns a tar archive of the image's filesystem layer.
137
+func (graph *Graph) TarLayer(img *Image) (arch archive.Archive, err error) {
138
+	if wd, ok := graph.driver.(*windows.WindowsGraphDriver); ok {
139
+		var ids []string
140
+		if img.Parent != "" {
141
+			parentImg, err := graph.Get(img.Parent)
142
+			if err != nil {
143
+				return nil, err
144
+			}
145
+
146
+			ids, err = graph.ParentLayerIds(parentImg)
147
+			if err != nil {
148
+				return nil, err
149
+			}
150
+		}
151
+
152
+		return wd.Export(img.ID, wd.LayerIdsToPaths(ids))
153
+	} else {
154
+		// We keep this functionality here so that we can still work with the VFS
155
+		// driver during development. VFS is not supported (and just will not work)
156
+		// for Windows containers.
157
+		return graph.driver.Diff(img.ID, img.Parent)
158
+	}
159
+}
... ...
@@ -5,13 +5,12 @@ import (
5 5
 	"strings"
6 6
 
7 7
 	"github.com/docker/docker/api/types"
8
-	"github.com/docker/docker/image"
9 8
 	"github.com/docker/docker/utils"
10 9
 )
11 10
 
12 11
 // WalkHistory calls the handler function for each image in the
13 12
 // provided images lineage starting from immediate parent.
14
-func (graph *Graph) WalkHistory(img *image.Image, handler func(image.Image) error) (err error) {
13
+func (graph *Graph) WalkHistory(img *Image, handler func(Image) error) (err error) {
15 14
 	currentImg := img
16 15
 	for currentImg != nil {
17 16
 		if handler != nil {
... ...
@@ -29,7 +28,7 @@ func (graph *Graph) WalkHistory(img *image.Image, handler func(image.Image) erro
29 29
 
30 30
 // depth returns the number of parents for a
31 31
 // current image
32
-func (graph *Graph) depth(img *image.Image) (int, error) {
32
+func (graph *Graph) depth(img *Image) (int, error) {
33 33
 	var (
34 34
 		count  = 0
35 35
 		parent = img
... ...
@@ -54,7 +53,7 @@ const MaxImageDepth = 127
54 54
 // CheckDepth returns an error if the depth of an image, as returned
55 55
 // by ImageDepth, is too large to support creating a container from it
56 56
 // on this daemon.
57
-func (graph *Graph) CheckDepth(img *image.Image) error {
57
+func (graph *Graph) CheckDepth(img *Image) error {
58 58
 	// We add 2 layers to the depth because the container's rw and
59 59
 	// init layer add to the restriction
60 60
 	depth, err := graph.depth(img)
... ...
@@ -86,7 +85,7 @@ func (s *TagStore) History(name string) ([]*types.ImageHistory, error) {
86 86
 
87 87
 	history := []*types.ImageHistory{}
88 88
 
89
-	err = s.graph.WalkHistory(foundImage, func(img image.Image) error {
89
+	err = s.graph.WalkHistory(foundImage, func(img Image) error {
90 90
 		history = append(history, &types.ImageHistory{
91 91
 			ID:        img.ID,
92 92
 			Created:   img.Created.Unix(),
... ...
@@ -101,14 +100,14 @@ func (s *TagStore) History(name string) ([]*types.ImageHistory, error) {
101 101
 	return history, err
102 102
 }
103 103
 
104
-func (graph *Graph) GetParent(img *image.Image) (*image.Image, error) {
104
+func (graph *Graph) GetParent(img *Image) (*Image, error) {
105 105
 	if img.Parent == "" {
106 106
 		return nil, nil
107 107
 	}
108 108
 	return graph.Get(img.Parent)
109 109
 }
110 110
 
111
-func (graph *Graph) GetParentsSize(img *image.Image, size int64) int64 {
111
+func (graph *Graph) GetParentsSize(img *Image, size int64) int64 {
112 112
 	parentImage, err := graph.GetParent(img)
113 113
 	if err != nil || parentImage == nil {
114 114
 		return size
... ...
@@ -8,7 +8,6 @@ import (
8 8
 
9 9
 	"github.com/Sirupsen/logrus"
10 10
 	"github.com/docker/docker/api/types"
11
-	"github.com/docker/docker/image"
12 11
 	"github.com/docker/docker/pkg/parsers/filters"
13 12
 	"github.com/docker/docker/utils"
14 13
 )
... ...
@@ -32,7 +31,7 @@ func (r ByCreated) Less(i, j int) bool { return r[i].Created < r[j].Created }
32 32
 
33 33
 func (s *TagStore) Images(config *ImagesConfig) ([]*types.Image, error) {
34 34
 	var (
35
-		allImages  map[string]*image.Image
35
+		allImages  map[string]*Image
36 36
 		err        error
37 37
 		filtTagged = true
38 38
 		filtLabel  = false
... ...
@@ -98,7 +98,7 @@ func (s *TagStore) recursiveLoad(address, tmpImageDir string) error {
98 98
 			logrus.Debugf("Error reading embedded tar", err)
99 99
 			return err
100 100
 		}
101
-		img, err := image.NewImgJSON(imageJson)
101
+		img, err := NewImgJSON(imageJson)
102 102
 		if err != nil {
103 103
 			logrus.Debugf("Error unmarshalling json", err)
104 104
 			return err
... ...
@@ -7,7 +7,6 @@ import (
7 7
 	"testing"
8 8
 
9 9
 	"github.com/docker/distribution/digest"
10
-	"github.com/docker/docker/image"
11 10
 	"github.com/docker/docker/registry"
12 11
 	"github.com/docker/docker/runconfig"
13 12
 	"github.com/docker/docker/utils"
... ...
@@ -124,7 +123,7 @@ func TestManifestTarsumCache(t *testing.T) {
124 124
 	if err != nil {
125 125
 		t.Fatal(err)
126 126
 	}
127
-	img := &image.Image{ID: testManifestImageID}
127
+	img := &Image{ID: testManifestImageID}
128 128
 	if err := store.graph.Register(img, archive); err != nil {
129 129
 		t.Fatal(err)
130 130
 	}
... ...
@@ -190,7 +189,7 @@ func TestManifestDigestCheck(t *testing.T) {
190 190
 	if err != nil {
191 191
 		t.Fatal(err)
192 192
 	}
193
-	img := &image.Image{ID: testManifestImageID}
193
+	img := &Image{ID: testManifestImageID}
194 194
 	if err := store.graph.Register(img, archive); err != nil {
195 195
 		t.Fatal(err)
196 196
 	}
... ...
@@ -13,7 +13,6 @@ import (
13 13
 	"github.com/Sirupsen/logrus"
14 14
 	"github.com/docker/distribution/digest"
15 15
 	"github.com/docker/docker/cliconfig"
16
-	"github.com/docker/docker/image"
17 16
 	"github.com/docker/docker/pkg/progressreader"
18 17
 	"github.com/docker/docker/pkg/streamformatter"
19 18
 	"github.com/docker/docker/pkg/stringid"
... ...
@@ -387,7 +386,7 @@ func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint
387 387
 				imgJSON []byte
388 388
 				imgSize int
389 389
 				err     error
390
-				img     *image.Image
390
+				img     *Image
391 391
 			)
392 392
 			retries := 5
393 393
 			for j := 1; j <= retries; j++ {
... ...
@@ -399,7 +398,7 @@ func (s *TagStore) pullImage(r *registry.Session, out io.Writer, imgID, endpoint
399 399
 					time.Sleep(time.Duration(j) * 500 * time.Millisecond)
400 400
 					continue
401 401
 				}
402
-				img, err = image.NewImgJSON(imgJSON)
402
+				img, err = NewImgJSON(imgJSON)
403 403
 				layersDownloaded = true
404 404
 				if err != nil && j == retries {
405 405
 					out.Write(sf.FormatProgress(stringid.TruncateID(id), "Error pulling dependent layers", nil))
... ...
@@ -540,7 +539,7 @@ func (s *TagStore) pullV2Tag(r *registry.Session, out io.Writer, endpoint *regis
540 540
 	// downloadInfo is used to pass information from download to extractor
541 541
 	type downloadInfo struct {
542 542
 		imgJSON    []byte
543
-		img        *image.Image
543
+		img        *Image
544 544
 		digest     digest.Digest
545 545
 		tmpFile    *os.File
546 546
 		length     int64
... ...
@@ -556,7 +555,7 @@ func (s *TagStore) pullV2Tag(r *registry.Session, out io.Writer, endpoint *regis
556 556
 			imgJSON = []byte(manifest.History[i].V1Compatibility)
557 557
 		)
558 558
 
559
-		img, err := image.NewImgJSON(imgJSON)
559
+		img, err := NewImgJSON(imgJSON)
560 560
 		if err != nil {
561 561
 			return false, fmt.Errorf("failed to parse json: %s", err)
562 562
 		}
... ...
@@ -11,7 +11,6 @@ import (
11 11
 	"github.com/Sirupsen/logrus"
12 12
 	"github.com/docker/distribution/digest"
13 13
 	"github.com/docker/docker/cliconfig"
14
-	"github.com/docker/docker/image"
15 14
 	"github.com/docker/docker/pkg/ioutils"
16 15
 	"github.com/docker/docker/pkg/progressreader"
17 16
 	"github.com/docker/docker/pkg/streamformatter"
... ...
@@ -349,7 +348,7 @@ func (s *TagStore) pushV2Repository(r *registry.Session, localRepo Repository, o
349 349
 		}
350 350
 
351 351
 		layersSeen := make(map[string]bool)
352
-		layers := []*image.Image{}
352
+		layers := []*Image{}
353 353
 		for ; layer != nil; layer, err = s.graph.GetParent(layer) {
354 354
 			if err != nil {
355 355
 				return err
... ...
@@ -445,7 +444,7 @@ func (s *TagStore) pushV2Repository(r *registry.Session, localRepo Repository, o
445 445
 }
446 446
 
447 447
 // PushV2Image pushes the image content to the v2 registry, first buffering the contents to disk
448
-func (s *TagStore) pushV2Image(r *registry.Session, img *image.Image, endpoint *registry.Endpoint, imageName string, sf *streamformatter.StreamFormatter, out io.Writer, auth *registry.RequestAuthorization) (digest.Digest, error) {
448
+func (s *TagStore) pushV2Image(r *registry.Session, img *Image, endpoint *registry.Endpoint, imageName string, sf *streamformatter.StreamFormatter, out io.Writer, auth *registry.RequestAuthorization) (digest.Digest, error) {
449 449
 	out.Write(sf.FormatProgress(stringid.TruncateID(img.ID), "Buffering to Disk", nil))
450 450
 
451 451
 	image, err := s.graph.Get(img.ID)
... ...
@@ -3,6 +3,7 @@ package graph
3 3
 import (
4 4
 	"fmt"
5 5
 	"io"
6
+	"runtime"
6 7
 
7 8
 	"github.com/Sirupsen/logrus"
8 9
 	"github.com/docker/docker/api/types"
... ...
@@ -58,17 +59,21 @@ func (s *TagStore) Lookup(name string) (*types.ImageInspect, error) {
58 58
 // ImageTarLayer return the tarLayer of the image
59 59
 func (s *TagStore) ImageTarLayer(name string, dest io.Writer) error {
60 60
 	if image, err := s.LookupImage(name); err == nil && image != nil {
61
-		fs, err := s.graph.TarLayer(image)
62
-		if err != nil {
63
-			return err
64
-		}
65
-		defer fs.Close()
61
+		// On Windows, the base layer cannot be exported
62
+		if runtime.GOOS != "windows" || image.Parent != "" {
63
+
64
+			fs, err := s.graph.TarLayer(image)
65
+			if err != nil {
66
+				return err
67
+			}
68
+			defer fs.Close()
66 69
 
67
-		written, err := io.Copy(dest, fs)
68
-		if err != nil {
69
-			return err
70
+			written, err := io.Copy(dest, fs)
71
+			if err != nil {
72
+				return err
73
+			}
74
+			logrus.Debugf("rendered layer for %s of [%d] size", image.ID, written)
70 75
 		}
71
-		logrus.Debugf("rendered layer for %s of [%d] size", image.ID, written)
72 76
 		return nil
73 77
 	}
74 78
 	return fmt.Errorf("No such image: %s", name)
... ...
@@ -15,7 +15,6 @@ import (
15 15
 
16 16
 	"github.com/docker/docker/daemon/events"
17 17
 	"github.com/docker/docker/graph/tags"
18
-	"github.com/docker/docker/image"
19 18
 	"github.com/docker/docker/pkg/parsers"
20 19
 	"github.com/docker/docker/pkg/stringid"
21 20
 	"github.com/docker/docker/registry"
... ...
@@ -126,7 +125,7 @@ func (store *TagStore) reload() error {
126 126
 	return nil
127 127
 }
128 128
 
129
-func (store *TagStore) LookupImage(name string) (*image.Image, error) {
129
+func (store *TagStore) LookupImage(name string) (*Image, error) {
130 130
 	// FIXME: standardize on returning nil when the image doesn't exist, and err for everything else
131 131
 	// (so we can pass all errors here)
132 132
 	repoName, ref := parsers.ParseRepositoryTag(name)
... ...
@@ -135,7 +134,7 @@ func (store *TagStore) LookupImage(name string) (*image.Image, error) {
135 135
 	}
136 136
 	var (
137 137
 		err error
138
-		img *image.Image
138
+		img *Image
139 139
 	)
140 140
 
141 141
 	img, err = store.GetImage(repoName, ref)
... ...
@@ -330,7 +329,7 @@ func (store *TagStore) Get(repoName string) (Repository, error) {
330 330
 	return nil, nil
331 331
 }
332 332
 
333
-func (store *TagStore) GetImage(repoName, refOrID string) (*image.Image, error) {
333
+func (store *TagStore) GetImage(repoName, refOrID string) (*Image, error) {
334 334
 	repo, err := store.Get(repoName)
335 335
 
336 336
 	if err != nil {
... ...
@@ -11,7 +11,6 @@ import (
11 11
 	"github.com/docker/docker/daemon/events"
12 12
 	"github.com/docker/docker/daemon/graphdriver"
13 13
 	_ "github.com/docker/docker/daemon/graphdriver/vfs" // import the vfs driver so it is used in the tests
14
-	"github.com/docker/docker/image"
15 14
 	"github.com/docker/docker/trust"
16 15
 	"github.com/docker/docker/utils"
17 16
 )
... ...
@@ -80,7 +79,7 @@ func mkTestTagStore(root string, t *testing.T) *TagStore {
80 80
 	if err != nil {
81 81
 		t.Fatal(err)
82 82
 	}
83
-	img := &image.Image{ID: testOfficialImageID}
83
+	img := &Image{ID: testOfficialImageID}
84 84
 	if err := graph.Register(img, officialArchive); err != nil {
85 85
 		t.Fatal(err)
86 86
 	}
... ...
@@ -91,7 +90,7 @@ func mkTestTagStore(root string, t *testing.T) *TagStore {
91 91
 	if err != nil {
92 92
 		t.Fatal(err)
93 93
 	}
94
-	img = &image.Image{ID: testPrivateImageID}
94
+	img = &Image{ID: testPrivateImageID}
95 95
 	if err := graph.Register(img, privateArchive); err != nil {
96 96
 		t.Fatal(err)
97 97
 	}
... ...
@@ -1,42 +1,12 @@
1 1
 package image
2 2
 
3 3
 import (
4
-	"encoding/json"
5 4
 	"fmt"
6 5
 	"regexp"
7
-	"time"
8
-
9
-	"github.com/docker/docker/runconfig"
10 6
 )
11 7
 
12 8
 var validHex = regexp.MustCompile(`^([a-f0-9]{64})$`)
13 9
 
14
-type Image struct {
15
-	ID              string            `json:"id"`
16
-	Parent          string            `json:"parent,omitempty"`
17
-	Comment         string            `json:"comment,omitempty"`
18
-	Created         time.Time         `json:"created"`
19
-	Container       string            `json:"container,omitempty"`
20
-	ContainerConfig runconfig.Config  `json:"container_config,omitempty"`
21
-	DockerVersion   string            `json:"docker_version,omitempty"`
22
-	Author          string            `json:"author,omitempty"`
23
-	Config          *runconfig.Config `json:"config,omitempty"`
24
-	Architecture    string            `json:"architecture,omitempty"`
25
-	OS              string            `json:"os,omitempty"`
26
-	Size            int64
27
-}
28
-
29
-// Build an Image object from raw json data
30
-func NewImgJSON(src []byte) (*Image, error) {
31
-	ret := &Image{}
32
-
33
-	// FIXME: Is there a cleaner way to "purify" the input json?
34
-	if err := json.Unmarshal(src, ret); err != nil {
35
-		return nil, err
36
-	}
37
-	return ret, nil
38
-}
39
-
40 10
 // Check wheather id is a valid image ID or not
41 11
 func ValidateID(id string) error {
42 12
 	if ok := validHex.MatchString(id); !ok {